Skip to content

Commit 74eb088

Browse files
authored
Merge pull request #437 from djhoese/feature-nogil-ewa
Add GIL releasing to EWA cython code
2 parents e531bd9 + bb06ebe commit 74eb088

File tree

2 files changed

+88
-64
lines changed

2 files changed

+88
-64
lines changed

pyresample/ewa/_fornav.pyx

+68-47
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ cdef extern from "_fornav_templates.h":
3939
ctypedef float ewa_param_type
4040
ctypedef float accum_type
4141
cdef float EPSILON
42-
# ctypedef double weight_type
43-
# ctypedef double ewa_param_type
44-
# ctypedef double accum_type
45-
# cdef double EPSILON
4642

4743
ctypedef struct ewa_parameters:
4844
ewa_param_type a
@@ -64,42 +60,42 @@ cdef extern from "_fornav_templates.h":
6460
weight_type * wtab
6561

6662
cdef int initialize_weight(size_t chan_count, unsigned int weight_count, weight_type weight_min, weight_type weight_distance_max,
67-
weight_type weight_delta_max, weight_type weight_sum_min, ewa_weight * ewaw)
68-
cdef void deinitialize_weight(ewa_weight * ewaw)
69-
cdef accum_type ** initialize_grid_accums(size_t chan_count, size_t grid_cols, size_t grid_rows)
70-
cdef weight_type ** initialize_grid_weights(size_t chan_count, size_t grid_cols, size_t grid_rows)
71-
cdef void deinitialize_grids(size_t chan_count, void ** grids)
63+
weight_type weight_delta_max, weight_type weight_sum_min, ewa_weight * ewaw) nogil
64+
cdef void deinitialize_weight(ewa_weight * ewaw) nogil
65+
cdef accum_type ** initialize_grid_accums(size_t chan_count, size_t grid_cols, size_t grid_rows) nogil
66+
cdef weight_type ** initialize_grid_weights(size_t chan_count, size_t grid_cols, size_t grid_rows) nogil
67+
cdef void deinitialize_grids(size_t chan_count, void ** grids) nogil
7268

7369
cdef int compute_ewa_parameters[CR_TYPE](size_t swath_cols, size_t swath_rows,
74-
CR_TYPE * uimg, CR_TYPE * vimg, ewa_weight * ewaw, ewa_parameters * ewap)
70+
CR_TYPE * uimg, CR_TYPE * vimg, ewa_weight * ewaw, ewa_parameters * ewap) nogil
7571

7672
cdef int compute_ewa[CR_TYPE, IMAGE_TYPE](
7773
size_t chan_count, bint maximum_weight_mode,
7874
size_t swath_cols, size_t swath_rows, size_t grid_cols, size_t grid_rows,
7975
CR_TYPE * uimg, CR_TYPE * vimg,
8076
IMAGE_TYPE ** images, IMAGE_TYPE img_fill, accum_type ** grid_accums, weight_type ** grid_weights,
81-
ewa_weight * ewaw, ewa_parameters * ewap)
77+
ewa_weight * ewaw, ewa_parameters * ewap) nogil
8278

8379
cdef int compute_ewa_single[CR_TYPE, IMAGE_TYPE](
8480
bint maximum_weight_mode,
8581
size_t swath_cols, size_t swath_rows, size_t grid_cols, size_t grid_rows,
8682
CR_TYPE * uimg, CR_TYPE * vimg,
8783
IMAGE_TYPE * image, IMAGE_TYPE img_fill, accum_type * grid_accum, weight_type * grid_weight,
88-
ewa_weight * ewaw, ewa_parameters * ewap)
84+
ewa_weight * ewaw, ewa_parameters * ewap) nogil
8985

9086
# For some reason cython can't deduce the type when using the template
9187
# cdef int write_grid_image[GRID_TYPE](GRID_TYPE *output_image, GRID_TYPE fill, size_t grid_cols, size_t grid_rows,
9288
# accum_type *grid_accum, weight_type *grid_weights,
9389
# int maximum_weight_mode, weight_type weight_sum_min)
9490
cdef unsigned int write_grid_image(numpy.float32_t * output_image, numpy.float32_t fill, size_t grid_cols, size_t grid_rows,
9591
accum_type * grid_accum, weight_type * grid_weights,
96-
int maximum_weight_mode, weight_type weight_sum_min)
92+
int maximum_weight_mode, weight_type weight_sum_min) nogil
9793
cdef unsigned int write_grid_image(numpy.float64_t * output_image, numpy.float64_t fill, size_t grid_cols, size_t grid_rows,
9894
accum_type * grid_accum, weight_type * grid_weights,
99-
int maximum_weight_mode, weight_type weight_sum_min)
95+
int maximum_weight_mode, weight_type weight_sum_min) nogil
10096
cdef unsigned int write_grid_image(numpy.int8_t * output_image, numpy.int8_t fill, size_t grid_cols, size_t grid_rows,
10197
accum_type * grid_accum, weight_type * grid_weights,
102-
int maximum_weight_mode, weight_type weight_sum_min)
98+
int maximum_weight_mode, weight_type weight_sum_min) nogil
10399

104100
ctypedef fused cr_dtype:
105101
numpy.float32_t
@@ -124,7 +120,7 @@ cdef int fornav(unsigned int * valid_list, size_t chan_count, size_t swath_cols,
124120
image_dtype ** input_arrays, grid_dtype ** output_arrays,
125121
image_dtype input_fill, grid_dtype output_fill, size_t rows_per_scan,
126122
unsigned int weight_count, weight_type weight_min, weight_type weight_distance_max, weight_type weight_delta_max,
127-
weight_type weight_sum_min, bint maximum_weight_mode) except -1:
123+
weight_type weight_sum_min, bint maximum_weight_mode) nogil except -1:
128124
cdef unsigned int row_idx
129125
cdef unsigned int idx
130126
cdef bint got_point = 0
@@ -279,54 +275,74 @@ def fornav_wrapper(numpy.ndarray[cr_dtype, ndim=2, mode='c'] cols_array,
279275
if not all(output_array.dtype == out_type for output_array in output_arrays):
280276
raise ValueError("Input arrays must all be of the same data type")
281277

282-
cdef void ** input_pointer = <void ** >malloc(num_items * sizeof(void * ))
278+
cdef void** input_pointer = <void ** >malloc(num_items * sizeof(void * ))
283279
if not input_pointer:
284280
raise MemoryError()
285-
cdef void ** output_pointer = <void ** >malloc(num_items * sizeof(void * ))
281+
cdef void** output_pointer = <void ** >malloc(num_items * sizeof(void * ))
286282
if not output_pointer:
287283
raise MemoryError()
288284
cdef unsigned int * valid_arr = <unsigned int * >malloc(num_items * sizeof(unsigned int))
289285
valid_list = []
290-
cdef numpy.ndarray[numpy.float32_t, ndim= 2] tmp_arr_f32
291-
cdef numpy.ndarray[numpy.float64_t, ndim= 2] tmp_arr_f64
292-
cdef numpy.ndarray[numpy.int8_t, ndim= 2] tmp_arr_i8
293286
cdef cr_dtype * cols_pointer = &cols_array[0, 0]
294287
cdef cr_dtype * rows_pointer = &rows_array[0, 0]
288+
cdef bint mwm = maximum_weight_mode
295289
cdef int func_result
290+
cdef numpy.float32_t input_fill_f32
291+
cdef numpy.float64_t input_fill_f64
292+
cdef numpy.int8_t input_fill_i8
293+
cdef numpy.float32_t output_fill_f32
294+
cdef numpy.float64_t output_fill_f64
295+
cdef numpy.int8_t output_fill_i8
296+
cdef numpy.ndarray[numpy.float32_t, ndim= 2] tmp_arr_f32
297+
cdef numpy.ndarray[numpy.float64_t, ndim= 2] tmp_arr_f64
298+
cdef numpy.ndarray[numpy.int8_t, ndim= 2] tmp_arr_i8
299+
cdef cr_dtype[:, ::1] tmp_arr
296300

297301
if in_type == numpy.float32:
302+
input_fill_f32 = <numpy.float32_t>input_fill
303+
output_fill_f32 = <numpy.float32_t>output_fill
298304
for i in range(num_items):
299305
tmp_arr_f32 = input_arrays[i]
300306
input_pointer[i] = &tmp_arr_f32[0, 0]
301307
tmp_arr_f32 = output_arrays[i]
302308
output_pointer[i] = &tmp_arr_f32[0, 0]
303-
func_result = fornav(valid_arr, num_items, swath_cols, swath_rows, grid_cols, grid_rows, cols_pointer, rows_pointer,
304-
< numpy.float32_t ** >input_pointer, < numpy.float32_t ** >output_pointer,
305-
< numpy.float32_t > input_fill, < numpy.float32_t > output_fill, rows_per_scan,
306-
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
307-
< bint > maximum_weight_mode)
309+
with nogil:
310+
func_result = fornav(valid_arr, num_items, swath_cols, swath_rows, grid_cols, grid_rows,
311+
cols_pointer, rows_pointer,
312+
< numpy.float32_t ** >input_pointer, < numpy.float32_t ** >output_pointer,
313+
output_fill_f32, output_fill_f32, rows_per_scan,
314+
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
315+
mwm)
308316
elif in_type == numpy.float64:
317+
input_fill_f64 = <numpy.float64_t>input_fill
318+
output_fill_f64 = <numpy.float64_t>output_fill
309319
for i in range(num_items):
310320
tmp_arr_f64 = input_arrays[i]
311321
input_pointer[i] = &tmp_arr_f64[0, 0]
312322
tmp_arr_f64 = output_arrays[i]
313323
output_pointer[i] = &tmp_arr_f64[0, 0]
314-
func_result = fornav(valid_arr, num_items, swath_cols, swath_rows, grid_cols, grid_rows, cols_pointer, rows_pointer,
315-
< numpy.float64_t ** >input_pointer, < numpy.float64_t ** >output_pointer,
316-
< numpy.float64_t > input_fill, < numpy.float64_t > output_fill, rows_per_scan,
317-
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
318-
< bint > maximum_weight_mode)
324+
with nogil:
325+
func_result = fornav(valid_arr, num_items, swath_cols, swath_rows, grid_cols, grid_rows,
326+
cols_pointer, rows_pointer,
327+
< numpy.float64_t ** >input_pointer, < numpy.float64_t ** >output_pointer,
328+
input_fill_f64, output_fill_f64, rows_per_scan,
329+
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
330+
mwm)
319331
elif in_type == numpy.int8:
332+
input_fill_i8 = <numpy.int8_t>input_fill
333+
output_fill_i8 = <numpy.int8_t>output_fill
320334
for i in range(num_items):
321335
tmp_arr_i8 = input_arrays[i]
322336
input_pointer[i] = &tmp_arr_i8[0, 0]
323337
tmp_arr_i8 = output_arrays[i]
324338
output_pointer[i] = &tmp_arr_i8[0, 0]
325-
func_result = fornav(valid_arr, num_items, swath_cols, swath_rows, grid_cols, grid_rows, cols_pointer, rows_pointer,
326-
< numpy.int8_t ** >input_pointer, < numpy.int8_t ** >output_pointer,
327-
< numpy.int8_t > input_fill, < numpy.int8_t > output_fill, rows_per_scan,
328-
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
329-
< bint > maximum_weight_mode)
339+
with nogil:
340+
func_result = fornav(valid_arr, num_items, swath_cols, swath_rows, grid_cols, grid_rows,
341+
cols_pointer, rows_pointer,
342+
< numpy.int8_t ** >input_pointer, < numpy.int8_t ** >output_pointer,
343+
input_fill_i8, output_fill_i8, rows_per_scan,
344+
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
345+
mwm)
330346
else:
331347
raise ValueError("Unknown input and output data type")
332348

@@ -347,7 +363,7 @@ cdef int fornav_weights_and_sums(
347363
image_dtype * input_array, weight_type * grid_weights, accum_type * grid_accums,
348364
image_dtype input_fill, grid_dtype output_fill, size_t rows_per_scan,
349365
unsigned int weight_count, weight_type weight_min, weight_type weight_distance_max, weight_type weight_delta_max,
350-
weight_type weight_sum_min, bint maximum_weight_mode) except -1:
366+
weight_type weight_sum_min, bint maximum_weight_mode) nogil except -1:
351367
"""Get the weights and sums arrays from the fornav algorithm.
352368
353369
Typically fornav performs the entire operation of computing the weights
@@ -482,12 +498,14 @@ def fornav_weights_and_sums_wrapper(numpy.ndarray[cr_dtype, ndim=2, mode='c'] co
482498
cdef weight_type * weights_pointer = &grid_weights[0, 0]
483499
cdef accum_type * accums_pointer = &grid_accums[0, 0]
484500
cdef int got_point
501+
cdef bint mwm = maximum_weight_mode
485502

486-
ret_val = fornav_weights_and_sums(swath_cols, swath_rows, grid_cols, grid_rows, cols_pointer, rows_pointer,
487-
input_pointer, weights_pointer, accums_pointer,
488-
input_fill, output_fill, rows_per_scan,
489-
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
490-
< bint > maximum_weight_mode)
503+
with nogil:
504+
ret_val = fornav_weights_and_sums(swath_cols, swath_rows, grid_cols, grid_rows, cols_pointer, rows_pointer,
505+
input_pointer, weights_pointer, accums_pointer,
506+
input_fill, output_fill, rows_per_scan,
507+
weight_count, weight_min, weight_distance_max, weight_delta_max, weight_sum_min,
508+
mwm)
491509

492510
succeeded = ret_val == 0
493511
return succeeded
@@ -501,8 +519,11 @@ def write_grid_image_single(numpy.ndarray[grid_dtype, ndim=2, mode='c'] output_a
501519
grid_dtype output_fill,
502520
weight_type weight_sum_min=-1.0,
503521
cpython.bool maximum_weight_mode=False):
504-
# unsigned int write_grid_image(GRID_TYPE *output_image, GRID_TYPE fill, size_t grid_cols, size_t grid_rows,
505-
# accum_type *grid_accum, weight_type *grid_weights,
506-
# int maximum_weight_mode, weight_type weight_sum_min) {
507-
return write_grid_image(& output_array[0, 0], output_fill, < size_t > output_array.shape[1], < size_t > output_array.shape[0],
508-
& grid_accums[0, 0], & grid_weights[0, 0], < int > maximum_weight_mode, weight_sum_min)
522+
cdef int mwm = <int>maximum_weight_mode
523+
cdef size_t grid_cols = <size_t>output_array.shape[1]
524+
cdef size_t grid_rows = <size_t>output_array.shape[0]
525+
cdef unsigned int result
526+
with nogil:
527+
result = write_grid_image(& output_array[0, 0], output_fill, grid_cols, grid_rows,
528+
& grid_accums[0, 0], & grid_weights[0, 0], mwm, weight_sum_min)
529+
return result

pyresample/ewa/_ll2cr.pyx

+20-17
Original file line numberDiff line numberDiff line change
@@ -226,39 +226,42 @@ def ll2cr_static(numpy.ndarray[cr_dtype, ndim=2] lon_arr, numpy.ndarray[cr_dtype
226226
Note longitude and latitude arrays are limited to 64-bit floats because
227227
of limitations in pyproj.
228228
"""
229+
# TODO: Rewrite so it is no GIL
229230
# pure python stuff for now
230231
p = Proj(proj4_definition)
231232

232233
# Pyproj currently makes a copy so we don't have to do anything special here
233234
cdef tuple projected_tuple = p(lon_arr, lat_arr)
234235
cdef cr_dtype[:, ::1] rows_out = projected_tuple[1]
235236
cdef cr_dtype[:, ::1] cols_out = projected_tuple[0]
237+
cdef cr_dtype[:, ::1] lons_view = lon_arr
238+
cdef cr_dtype[:, ::1] lats_view = lat_arr
236239

237240
# indexes
238241
cdef unsigned int row
239242
cdef unsigned int col
240243
# index bounds
241-
cdef unsigned int num_rows = lon_arr.shape[0]
242-
cdef unsigned int num_cols = lon_arr.shape[1]
244+
cdef unsigned int num_rows = lons_view.shape[0]
245+
cdef unsigned int num_cols = lons_view.shape[1]
243246
cdef cr_dtype x_tmp
244247
cdef cr_dtype y_tmp
245248
cdef unsigned int points_in_grid = 0
246249

247-
for row in range(num_rows):
248-
for col in range(num_cols):
249-
x_tmp = cols_out[row, col]
250-
y_tmp = rows_out[row, col]
251-
if x_tmp >= 1e30:
252-
lon_arr[row, col] = fill_in
253-
lat_arr[row, col] = fill_in
254-
continue
250+
with nogil:
251+
for row in range(num_rows):
252+
for col in range(num_cols):
253+
x_tmp = cols_out[row, col]
254+
y_tmp = rows_out[row, col]
255+
if x_tmp >= 1e30:
256+
lons_view[row, col] = fill_in
257+
lats_view[row, col] = fill_in
258+
continue
255259

256-
x_tmp = (x_tmp - origin_x) / cell_width
257-
y_tmp = (y_tmp - origin_y) / cell_height
258-
if x_tmp >= -1 and x_tmp <= width + 1 and y_tmp >= -1 and y_tmp <= height + 1:
259-
points_in_grid += 1
260-
lon_arr[row, col] = x_tmp
261-
lat_arr[row, col] = y_tmp
260+
x_tmp = (x_tmp - origin_x) / cell_width
261+
y_tmp = (y_tmp - origin_y) / cell_height
262+
if x_tmp >= -1 and x_tmp <= width + 1 and y_tmp >= -1 and y_tmp <= height + 1:
263+
points_in_grid += 1
264+
lons_view[row, col] = x_tmp
265+
lats_view[row, col] = y_tmp
262266

263-
# return points_in_grid, x_arr, y_arr
264267
return points_in_grid

0 commit comments

Comments
 (0)