Skip to content

Commit 758a1a9

Browse files
Liang YuGitHub Enterprise
authored andcommitted
CUDA geocode for InSAR workflow (#820)
* CUDA nearest neighbor interp2d commit * added unsigned char support to CUDA interp2d * initial commit of CUDA geocode workflow CUDA and CPU geocode split into 2 functions due differences in block processing * temporary fix for CUDA GUNW's inability to directly write to HDF5 with chunks
1 parent 15b3aec commit 758a1a9

File tree

14 files changed

+621
-259
lines changed

14 files changed

+621
-259
lines changed

cxx/isce3/cuda/Sources.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ core/gpuBicubicInterpolator.cu
55
core/gpuBilinearInterpolator.cu
66
core/gpuLUT1d.cu
77
core/gpuLUT2d.cu
8+
core/gpuNearestNeighborInterpolator.cu
89
core/gpuPoly2d.cu
910
core/gpuProjections.cu
1011
core/gpuSinc2dInterpolator.cu

cxx/isce3/cuda/core/InterpolatorHandle.cu

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@ __global__ void init_interp(DeviceInterp<T>** interp,
2020
{
2121
if (threadIdx.x == 0 && blockIdx.x == 0) {
2222
// Choose interpolator
23-
switch (interp_method) {
24-
case isce3::core::BILINEAR_METHOD:
25-
(*interp) = new isce3::cuda::core::gpuBilinearInterpolator<T>();
26-
break;
27-
case isce3::core::BICUBIC_METHOD:
28-
(*interp) = new isce3::cuda::core::gpuBicubicInterpolator<T>();
29-
break;
30-
case isce3::core::BIQUINTIC_METHOD: {
31-
size_t order = 6;
32-
(*interp) =
33-
new isce3::cuda::core::gpuSpline2dInterpolator<T>(order);
34-
break;
35-
}
36-
default: *unsupported_interp = true; break;
23+
switch(interp_method) {
24+
case isce3::core::BILINEAR_METHOD:
25+
(*interp) = new isce3::cuda::core::gpuBilinearInterpolator<T>();
26+
break;
27+
case isce3::core::BICUBIC_METHOD:
28+
(*interp) = new isce3::cuda::core::gpuBicubicInterpolator<T>();
29+
break;
30+
case isce3::core::BIQUINTIC_METHOD:
31+
size_t order = 6;
32+
(*interp) = new isce3::cuda::core::gpuSpline2dInterpolator<T>(order);
33+
break;
34+
case isce3::core::NEAREST_METHOD:
35+
(*interp) = new isce3::cuda::core::gpuNearestNeighborInterpolator<T>();
36+
break;
37+
default:
38+
*unsupported_interp = true;
39+
break;
3740
}
3841
}
3942
}
@@ -82,4 +85,5 @@ template class InterpolatorHandle<float>;
8285
template class InterpolatorHandle<thrust::complex<float>>;
8386
template class InterpolatorHandle<double>;
8487
template class InterpolatorHandle<thrust::complex<double>>;
88+
template class InterpolatorHandle<unsigned char>;
8589
} // namespace isce3::cuda::core

cxx/isce3/cuda/core/gpuBicubicInterpolator.cu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ template class gpuBicubicInterpolator<double>;
178178
template class gpuBicubicInterpolator<thrust::complex<double>>;
179179
template class gpuBicubicInterpolator<float>;
180180
template class gpuBicubicInterpolator<thrust::complex<float>>;
181+
template class gpuBicubicInterpolator<unsigned char>;
181182

182183
template __global__ void gpuInterpolator_g<double>(
183184
gpuBicubicInterpolator<double> interp, double* x, double* y,

cxx/isce3/cuda/core/gpuBilinearInterpolator.cu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ template class gpuBilinearInterpolator<double>;
114114
template class gpuBilinearInterpolator<thrust::complex<double>>;
115115
template class gpuBilinearInterpolator<float>;
116116
template class gpuBilinearInterpolator<thrust::complex<float>>;
117+
template class gpuBilinearInterpolator<unsigned char>;
117118

118119
template __global__ void gpuInterpolator_g<double>(
119120
gpuBilinearInterpolator<double> interp, double* x, double* y,

cxx/isce3/cuda/core/gpuInterpolator.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,13 @@ class gpuSinc2dInterpolator : public isce3::cuda::core::gpuInterpolator<U> {
7575
CUDA_DEV U interpolate(double, double, const U*, size_t, size_t);
7676
CUDA_HOST void interpolate_h(const Matrix<double>&, Matrix<U>&, double, double, U*);
7777
};
78+
79+
/** gpuNearestNeighborInterpolator class derived from abstract gpuInterpolator class */
80+
template <class T>
81+
class gpuNearestNeighborInterpolator : public isce3::cuda::core::gpuInterpolator<T> {
82+
public:
83+
CUDA_HOSTDEV gpuNearestNeighborInterpolator(){};
84+
CUDA_DEV T interpolate(double x, double y, const T* z, size_t nx, size_t ny = 0);
85+
};
86+
7887
}}}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "gpuInterpolator.h"
2+
3+
#include <thrust/complex.h>
4+
5+
using isce3::cuda::core::gpuNearestNeighborInterpolator;
6+
7+
template<class T>
8+
__device__ T gpuNearestNeighborInterpolator<T>::interpolate(
9+
double x, double y, const T* z, size_t nx, size_t /*ny*/)
10+
{
11+
size_t x_round = static_cast<size_t>(std::round(x));
12+
size_t y_round = static_cast<size_t>(std::round(y));
13+
14+
return z[y_round * nx + x_round];
15+
}
16+
17+
template class gpuNearestNeighborInterpolator<double>;
18+
template class gpuNearestNeighborInterpolator<thrust::complex<double>>;
19+
template class gpuNearestNeighborInterpolator<float>;
20+
template class gpuNearestNeighborInterpolator<thrust::complex<float>>;
21+
template class gpuNearestNeighborInterpolator<unsigned char>;

cxx/isce3/cuda/core/gpuSpline2dInterpolator.cu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ template class gpuSpline2dInterpolator<double>;
153153
template class gpuSpline2dInterpolator<thrust::complex<double>>;
154154
template class gpuSpline2dInterpolator<float>;
155155
template class gpuSpline2dInterpolator<thrust::complex<float>>;
156+
template class gpuSpline2dInterpolator<unsigned char>;
156157

157158
template __global__ void gpuInterpolator_g<double>(
158159
gpuSpline2dInterpolator<double> interp, double* x, double* y,

cxx/isce3/cuda/geocode/Geocode.cu

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -172,26 +172,35 @@ __global__ void interpolate(T* geo_data_block, const double* __restrict__ rdr_x,
172172
geo_data_block[tid] = interp_val;
173173
}
174174

175-
__host__ Geocode::Geocode(const isce3::product::GeoGridParameters& geogrid,
176-
const isce3::container::RadarGeometry& rdr_geom,
177-
const Raster& dem_raster, const double dem_margin,
178-
const size_t lines_per_block,
179-
const isce3::core::dataInterpMethod data_interp_method,
180-
const isce3::core::dataInterpMethod dem_interp_method,
181-
const double threshold, const int maxiter, const double dr,
182-
const float invalid_value)
183-
: _geogrid(geogrid), _rdr_geom(rdr_geom),
184-
_ellipsoid(isce3::core::makeProjection(_geogrid.epsg())->ellipsoid()),
185-
_lines_per_block(lines_per_block), _geo_block_length(_lines_per_block),
186-
_n_blocks((geogrid.length() + _lines_per_block - 1) / _lines_per_block),
187-
_az_first_line(_rdr_geom.radarGrid().length() - 1), _az_last_line(0),
188-
_range_first_pixel(_rdr_geom.radarGrid().width() - 1),
189-
_range_last_pixel(0), _dem_raster(dem_raster), _dem_margin(dem_margin),
190-
_interp_float_handle(data_interp_method),
191-
_interp_cfloat_handle(data_interp_method),
192-
_interp_double_handle(data_interp_method),
193-
_interp_cdouble_handle(data_interp_method), _proj_handle(geogrid.epsg()),
194-
_dem_interp_method(dem_interp_method)
175+
__host__
176+
Geocode::Geocode(const isce3::product::GeoGridParameters & geogrid,
177+
const isce3::container::RadarGeometry & rdr_geom,
178+
const Raster & dem_raster,
179+
const double dem_margin,
180+
const size_t lines_per_block,
181+
const isce3::core::dataInterpMethod data_interp_method,
182+
const isce3::core::dataInterpMethod dem_interp_method,
183+
const double threshold, const int maxiter,
184+
const double dr, const float invalid_value) :
185+
_geogrid(geogrid),
186+
_rdr_geom(rdr_geom),
187+
_ellipsoid(isce3::core::makeProjection(_geogrid.epsg())->ellipsoid()),
188+
_lines_per_block(lines_per_block),
189+
_geo_block_length(_lines_per_block),
190+
_n_blocks((geogrid.length() + _lines_per_block -1) / _lines_per_block),
191+
_az_first_line(_rdr_geom.radarGrid().length() - 1),
192+
_az_last_line(0),
193+
_range_first_pixel(_rdr_geom.radarGrid().width() - 1),
194+
_range_last_pixel(0),
195+
_dem_raster(dem_raster),
196+
_dem_margin(dem_margin),
197+
_interp_float_handle(data_interp_method),
198+
_interp_cfloat_handle(data_interp_method),
199+
_interp_double_handle(data_interp_method),
200+
_interp_cdouble_handle(data_interp_method),
201+
_interp_unsigned_char_handle(data_interp_method),
202+
_proj_handle(geogrid.epsg()),
203+
_dem_interp_method(dem_interp_method)
195204
{
196205
// init light weight radar grid
197206
_radar_grid.sensing_start = _rdr_geom.radarGrid().sensingStart();
@@ -219,9 +228,11 @@ __host__ Geocode::Geocode(const isce3::product::GeoGridParameters& geogrid,
219228
if (std::isnan(invalid_value)) {
220229
_invalid_float = std::numeric_limits<float>::quiet_NaN();
221230
_invalid_double = std::numeric_limits<double>::quiet_NaN();
231+
_invalid_unsigned_char = 255;
222232
} else {
223233
_invalid_float = invalid_value;
224-
_invalid_double = (double) invalid_value;
234+
_invalid_double = static_cast<double>(invalid_value);
235+
_invalid_unsigned_char = static_cast<unsigned char>(invalid_value);
225236
}
226237
}
227238

@@ -334,8 +345,11 @@ void Geocode::geocodeRasterBlock(Raster& output_raster, Raster& input_raster)
334345
invalid_value = _invalid_double;
335346
} else if constexpr (std::is_same_v<T, thrust::complex<double>>) {
336347
interp = _interp_cdouble_handle.getInterp();
337-
invalid_value =
338-
thrust::complex<double>(_invalid_double, _invalid_double);
348+
invalid_value = thrust::complex<double>(_invalid_double,
349+
_invalid_double);
350+
} else if constexpr (std::is_same_v<T, unsigned char>) {
351+
interp = _interp_unsigned_char_handle.getInterp();
352+
invalid_value = _invalid_unsigned_char;
339353
}
340354

341355
// 0 width indicates current block is out of bounds
@@ -396,4 +410,5 @@ EXPLICIT_INSTATIATION(float);
396410
EXPLICIT_INSTATIATION(thrust::complex<float>);
397411
EXPLICIT_INSTATIATION(double);
398412
EXPLICIT_INSTATIATION(thrust::complex<double>);
413+
EXPLICIT_INSTATIATION(unsigned char);
399414
} // namespace isce3::cuda::geocode

cxx/isce3/cuda/geocode/Geocode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,13 @@ class Geocode {
163163
isce3::cuda::core::InterpolatorHandle<double> _interp_double_handle;
164164
isce3::cuda::core::InterpolatorHandle<thrust::complex<double>>
165165
_interp_cdouble_handle;
166+
isce3::cuda::core::InterpolatorHandle<unsigned char>
167+
_interp_unsigned_char_handle;
166168

167169
// value applied to invalid geogrid pixels
168170
float _invalid_float;
169171
double _invalid_double;
172+
unsigned char _invalid_unsigned_char;
170173

171174
isce3::core::dataInterpMethod _dem_interp_method;
172175
};

python/extensions/pybind_isce3/cuda/geocode/cuGeocode.cpp

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -72,40 +72,40 @@ void addbinding(pybind11::class_<Geocode>& pyGeocode)
7272
Index of block of raster where radar grid coordinates are calculated
7373
and set.
7474
)")
75-
.def(
76-
"geocode_raster_block",
77-
[](Geocode& self, isce3::io::Raster& output_raster,
78-
isce3::io::Raster& input_raster) {
79-
const int dtype = input_raster.dtype();
80-
switch (dtype) {
81-
case GDT_Float32: {
82-
self.geocodeRasterBlock<float>(
83-
output_raster, input_raster);
84-
break;
85-
}
86-
case GDT_CFloat32: {
87-
self.geocodeRasterBlock<thrust::complex<float>>(
88-
output_raster, input_raster);
89-
break;
90-
}
91-
case GDT_Float64: {
92-
self.geocodeRasterBlock<double>(
93-
output_raster, input_raster);
94-
break;
95-
}
96-
case GDT_CFloat64: {
97-
self.geocodeRasterBlock<thrust::complex<double>>(
98-
output_raster, input_raster);
99-
break;
100-
}
101-
default: {
102-
throw isce3::except::RuntimeError(
103-
ISCE_SRCINFO(), "unsupported datatype");
104-
}
105-
}
106-
},
107-
py::arg("output_raster"), py::arg("input_raster"),
108-
R"(
75+
.def("geocode_raster_block", [](Geocode & self,
76+
isce3::io::Raster & output_raster,
77+
isce3::io::Raster & input_raster) {
78+
const int dtype = input_raster.dtype();
79+
switch (dtype) {
80+
case GDT_Float32: {
81+
self.geocodeRasterBlock<float>(
82+
output_raster, input_raster);
83+
break; }
84+
case GDT_CFloat32: {
85+
self.geocodeRasterBlock<thrust::complex<float>>(
86+
output_raster, input_raster);
87+
break;}
88+
case GDT_Float64: {
89+
self.geocodeRasterBlock<double>(
90+
output_raster, input_raster);
91+
break; }
92+
case GDT_CFloat64: {
93+
self.geocodeRasterBlock<thrust::complex<double>>(
94+
output_raster, input_raster);
95+
break;}
96+
case GDT_Byte: {
97+
self.geocodeRasterBlock<unsigned char>(
98+
output_raster, input_raster);
99+
break;}
100+
default: {
101+
throw isce3::except::RuntimeError(ISCE_SRCINFO(),
102+
"unsupported datatype");
103+
}
104+
}
105+
},
106+
py::arg("output_raster"),
107+
py::arg("input_raster"),
108+
R"(
109109
Geocode raster according to block specified in make_radar_grid_coordinates.
110110
111111
Parameters

0 commit comments

Comments
 (0)