This is an automated email from the ASF dual-hosted git repository.
paleolimbot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-db.git
The following commit(s) were added to refs/heads/main by this push:
new 82c1bb05 feat(c/sedona-libgpuspatial): Change the interface of
SpatialRefiner (#717)
82c1bb05 is described below
commit 82c1bb05a105c428c1831fb7226b72a40896029c
Author: Liang Geng <[email protected]>
AuthorDate: Thu Mar 19 05:57:32 2026 +0800
feat(c/sedona-libgpuspatial): Change the interface of SpatialRefiner (#717)
---
.../include/gpuspatial/gpuspatial_c.h | 14 +++++---
.../libgpuspatial/src/gpuspatial_c.cc | 38 ++++++++++------------
.../libgpuspatial/test/c_wrapper_test.cc | 10 +++---
c/sedona-libgpuspatial/src/lib.rs | 16 ++++-----
c/sedona-libgpuspatial/src/libgpuspatial.rs | 26 ++++++---------
5 files changed, 51 insertions(+), 53 deletions(-)
diff --git
a/c/sedona-libgpuspatial/libgpuspatial/include/gpuspatial/gpuspatial_c.h
b/c/sedona-libgpuspatial/libgpuspatial/include/gpuspatial/gpuspatial_c.h
index 5842bbd5..0b949f31 100644
--- a/c/sedona-libgpuspatial/libgpuspatial/include/gpuspatial/gpuspatial_c.h
+++ b/c/sedona-libgpuspatial/libgpuspatial/include/gpuspatial/gpuspatial_c.h
@@ -155,9 +155,13 @@ struct SedonaSpatialRefiner {
/** Clear all built geometries from the refiner */
int (*clear)(struct SedonaSpatialRefiner* self);
- int (*init_schema)(struct SedonaSpatialRefiner* self,
- const struct ArrowSchema* build_schema,
- const struct ArrowSchema* probe_schema);
+ /** Initialize the spatial refiner with the schema of the build geometries
+ *
+ * @param build_schema The Arrow schema of the build geometries;
+ * @return 0 on success, non-zero on failure
+ */
+ int (*init_build_schema)(struct SedonaSpatialRefiner* self,
+ const struct ArrowSchema* build_schema);
/** Push geometries for building the spatial refiner
*
@@ -177,6 +181,7 @@ struct SedonaSpatialRefiner {
* Refine candidate pairs of geometries
*
* @param probe_array The Arrow array of the probe geometries
+ * @param probe_schema The Arrow schema of the probe geometries
* @param predicate The spatial relation predicate to evaluate
* @param build_indices An array of build-side indices corresponding to
candidate pairs.
* This is a global index from 0 to N-1, where N is the total number of
build geometries
@@ -188,7 +193,8 @@ struct SedonaSpatialRefiner {
* @param new_indices_size Output parameter to store the number of refined
pairs
* @return 0 on success, non-zero on failure
*/
- int (*refine)(struct SedonaSpatialRefiner* self, const struct ArrowArray*
probe_array,
+ int (*refine)(struct SedonaSpatialRefiner* self, const struct ArrowSchema*
probe_schema,
+ const struct ArrowArray* probe_array,
enum SedonaSpatialRelationPredicate predicate, uint32_t*
build_indices,
uint32_t* probe_indices, uint32_t indices_size,
uint32_t* new_indices_size);
diff --git a/c/sedona-libgpuspatial/libgpuspatial/src/gpuspatial_c.cc
b/c/sedona-libgpuspatial/libgpuspatial/src/gpuspatial_c.cc
index 0e0c5627..e0fae7a4 100644
--- a/c/sedona-libgpuspatial/libgpuspatial/src/gpuspatial_c.cc
+++ b/c/sedona-libgpuspatial/libgpuspatial/src/gpuspatial_c.cc
@@ -271,7 +271,6 @@ struct GpuSpatialRefinerExporter {
struct Payload {
std::unique_ptr<gpuspatial::SpatialRefiner> refiner;
nanoarrow::UniqueArrayView build_array_view;
- nanoarrow::UniqueArrayView probe_array_view;
runtime_data_t* rdata;
};
using private_data_t = GpuSpatialWrapper<Payload>;
@@ -293,16 +292,14 @@ struct GpuSpatialRefinerExporter {
auto refiner = gpuspatial::CreateRTSpatialRefiner(refiner_config);
out->clear = &CClear;
- out->init_schema = &CInitSchema;
+ out->init_build_schema = &CInitBuildSchema;
out->push_build = &CPushBuild;
out->finish_building = &CFinishBuilding;
out->refine = &CRefine;
out->get_last_error = &CGetLastError;
out->release = &CRelease;
- out->private_data =
- new private_data_t{Payload{std::move(refiner),
nanoarrow::UniqueArrayView(),
- nanoarrow::UniqueArrayView(), rdata},
- ""};
+ out->private_data = new private_data_t{
+ Payload{std::move(refiner), nanoarrow::UniqueArrayView(), rdata}, ""};
}
static int CClear(SedonaSpatialRefiner* self) {
@@ -310,8 +307,8 @@ struct GpuSpatialRefinerExporter {
[&] { use_refiner(self).Clear(); });
}
- static int CInitSchema(SedonaSpatialRefiner* self, const ArrowSchema*
build_schema,
- const ArrowSchema* probe_schema) {
+ static int CInitBuildSchema(SedonaSpatialRefiner* self,
+ const ArrowSchema* build_schema) {
return SafeExecute(static_cast<private_data_t*>(self->private_data), [&] {
auto* private_data = static_cast<private_data_t*>(self->private_data);
ArrowError arrow_error;
@@ -320,11 +317,6 @@ struct GpuSpatialRefinerExporter {
throw std::runtime_error("ArrowArrayViewInitFromSchema error " +
std::string(arrow_error.message));
}
- if
(ArrowArrayViewInitFromSchema(private_data->payload.probe_array_view.get(),
- probe_schema, &arrow_error) !=
NANOARROW_OK) {
- throw std::runtime_error("ArrowArrayViewInitFromSchema error " +
- std::string(arrow_error.message));
- }
});
}
@@ -348,23 +340,29 @@ struct GpuSpatialRefinerExporter {
[&] { use_refiner(self).FinishBuilding(); });
}
- static int CRefine(SedonaSpatialRefiner* self, const ArrowArray* probe_array,
+ static int CRefine(SedonaSpatialRefiner* self, const ArrowSchema*
probe_schema,
+ const ArrowArray* probe_array,
SedonaSpatialRelationPredicate predicate, uint32_t*
build_indices,
uint32_t* probe_indices, uint32_t indices_size,
uint32_t* new_indices_size) {
return SafeExecute(static_cast<private_data_t*>(self->private_data), [&] {
- auto* private_data = static_cast<private_data_t*>(self->private_data);
- auto* array_view = private_data->payload.build_array_view.get();
+ // We need to create a local ArrayView to make sure this method is
thread-safe
ArrowError arrow_error;
-
- if (ArrowArrayViewSetArray(array_view, probe_array, &arrow_error) !=
NANOARROW_OK) {
+ nanoarrow::UniqueArrayView probe_array_view;
+ if (ArrowArrayViewInitFromSchema(probe_array_view.get(), probe_schema,
+ &arrow_error) != NANOARROW_OK) {
+ throw std::runtime_error("ArrowArrayViewInitFromSchema error " +
+ std::string(arrow_error.message));
+ }
+ if (ArrowArrayViewSetArray(probe_array_view.get(), probe_array,
&arrow_error) !=
+ NANOARROW_OK) {
throw std::runtime_error("ArrowArrayViewSetArray error " +
std::string(arrow_error.message));
}
*new_indices_size = use_refiner(self).Refine(
- array_view, static_cast<gpuspatial::Predicate>(predicate),
build_indices,
- probe_indices, indices_size);
+ probe_array_view.get(),
static_cast<gpuspatial::Predicate>(predicate),
+ build_indices, probe_indices, indices_size);
});
}
diff --git a/c/sedona-libgpuspatial/libgpuspatial/test/c_wrapper_test.cc
b/c/sedona-libgpuspatial/libgpuspatial/test/c_wrapper_test.cc
index 35f850f0..481fe9f2 100644
--- a/c/sedona-libgpuspatial/libgpuspatial/test/c_wrapper_test.cc
+++ b/c/sedona-libgpuspatial/libgpuspatial/test/c_wrapper_test.cc
@@ -122,7 +122,7 @@ class CWrapperTest : public ::testing::Test {
runtime_config.ptx_root = ptx_root.c_str();
runtime_config.device_id = 0;
- runtime_config.use_cuda_memory_pool = true;
+ runtime_config.use_cuda_memory_pool = false;
runtime_config.cuda_memory_pool_init_precent = 10;
ASSERT_EQ(runtime_.init(&runtime_, &runtime_config), 0);
@@ -242,8 +242,6 @@ TEST_F(CWrapperTest, InitializeJoiner) {
NANOARROW_OK)
<< error.message;
- refiner_.init_schema(&refiner_, build_schema.get(), probe_schema.get());
-
for (int64_t j = 0; j < probe_array->length; j++) {
ArrowBufferView wkb = ArrowArrayViewGetBytesUnsafe(probe_view.get(), j);
auto geom = wkb_reader.read(wkb.data.as_uint8, wkb.size_bytes);
@@ -282,13 +280,17 @@ TEST_F(CWrapperTest, InitializeJoiner) {
},
&intersection_ids);
+ if (i == 0) {
+ ASSERT_EQ(refiner_.init_build_schema(&refiner_, build_schema.get()), 0);
+ }
+
refiner_.clear(&refiner_);
ASSERT_EQ(refiner_.push_build(&refiner_, build_array.get()), 0);
ASSERT_EQ(refiner_.finish_building(&refiner_), 0);
uint32_t new_len;
ASSERT_EQ(refiner_.refine(
- &refiner_, probe_array.get(),
+ &refiner_, probe_schema.get(), probe_array.get(),
SedonaSpatialRelationPredicate::SedonaSpatialPredicateContains,
intersection_ids.build_indices_ptr,
intersection_ids.probe_indices_ptr,
intersection_ids.length, &new_len),
diff --git a/c/sedona-libgpuspatial/src/lib.rs
b/c/sedona-libgpuspatial/src/lib.rs
index 5dc05a60..437a35e8 100644
--- a/c/sedona-libgpuspatial/src/lib.rs
+++ b/c/sedona-libgpuspatial/src/lib.rs
@@ -151,10 +151,9 @@ mod sys {
Ok(Self { inner })
}
- /// Initializes the schema for the refiner based on the data types of
the build and probe geometries.
- /// This allows the refiner to understand how to interpret the
geometry data for both sets.
- pub fn init_schema(&mut self, build: &DataType, probe: &DataType) ->
Result<()> {
- self.inner.init_schema(build, probe)
+ /// Initializes the schema for the refiner based on the data types of
the build geometries.
+ pub fn init_build_schema(&mut self, build: &DataType) -> Result<()> {
+ self.inner.init_build_schema(build)
}
/// Clears any previously inserted data from the refiner, allowing it
to be reused for building a new set of geometries.
@@ -207,7 +206,7 @@ mod sys {
pub fn push_build(&mut self, _r: &[Rect<f32>]) -> Result<()> {
Err(GpuSpatialError::GpuNotAvailable)
}
- pub fn finish_building(self) -> Result<GpuSpatialIndex> {
+ pub fn finish_building(&mut self) -> Result<GpuSpatialIndex> {
Err(GpuSpatialError::GpuNotAvailable)
}
pub fn probe(&self, _r: &[Rect<f32>]) -> Result<(Vec<u32>, Vec<u32>)> {
@@ -219,9 +218,10 @@ mod sys {
pub fn try_new(_opts: &GpuSpatialOptions) -> Result<Self> {
Err(GpuSpatialError::GpuNotAvailable)
}
- pub fn init_schema(&mut self, _b: &DataType, _p: &DataType) ->
Result<()> {
+ pub fn init_build_schema(&mut self, _b: &DataType) -> Result<()> {
Err(GpuSpatialError::GpuNotAvailable)
}
+
pub fn clear(&mut self) {}
pub fn push_build(&mut self, _arr: &arrow_array::ArrayRef) ->
Result<()> {
Err(GpuSpatialError::GpuNotAvailable)
@@ -319,9 +319,7 @@ mod tests {
let points = create_array_storage(point_values, &WKB_GEOMETRY);
// 2. Build Refiner
- refiner
- .init_schema(polygons.data_type(), points.data_type())
- .unwrap();
+ refiner.init_build_schema(polygons.data_type()).unwrap();
refiner.push_build(&polygons).unwrap();
diff --git a/c/sedona-libgpuspatial/src/libgpuspatial.rs
b/c/sedona-libgpuspatial/src/libgpuspatial.rs
index 8a53b61d..f1cb2e92 100644
--- a/c/sedona-libgpuspatial/src/libgpuspatial.rs
+++ b/c/sedona-libgpuspatial/src/libgpuspatial.rs
@@ -346,7 +346,7 @@ impl Refiner {
) -> Result<Self, GpuSpatialError> {
let mut refiner = SedonaSpatialRefiner {
clear: None,
- init_schema: None,
+ init_build_schema: None,
push_build: None,
finish_building: None,
refine: None,
@@ -377,26 +377,19 @@ impl Refiner {
/// Initializes the schema for the refiner using the provided build and
probe data types.
/// It converts the Arrow `DataType` to the C-compatible `FFI_ArrowSchema`
and calls the underlying C function.
/// If initialization fails, it retrieves the error message from the C
struct and returns a `GpuSpatialError`.
- pub fn init_schema(
- &mut self,
- build_dt: &DataType,
- probe_dt: &DataType,
- ) -> Result<(), GpuSpatialError> {
+ pub fn init_build_schema(&mut self, build_dt: &DataType) -> Result<(),
GpuSpatialError> {
let build_ffi = FFI_ArrowSchema::try_from(build_dt)?;
- let probe_ffi = FFI_ArrowSchema::try_from(probe_dt)?;
- let init_fn = self.inner.refiner.init_schema.unwrap();
+ let init_fn = self
+ .inner
+ .refiner
+ .init_build_schema
+ .expect("init_build_schema function is None");
let get_last_error = self.inner.refiner.get_last_error;
let refiner_ptr = &mut self.inner.refiner as *mut SedonaSpatialRefiner;
unsafe {
check_ffi_call(
- || {
- init_fn(
- &mut self.inner.refiner,
- &build_ffi as *const _ as *const _,
- &probe_ffi as *const _ as *const _,
- )
- },
+ || init_fn(&mut self.inner.refiner, &build_ffi as *const _ as
*const _),
get_last_error,
refiner_ptr,
GpuSpatialError::Init,
@@ -464,7 +457,7 @@ impl Refiner {
build_indices: &mut Vec<u32>,
probe_indices: &mut Vec<u32>,
) -> Result<(), GpuSpatialError> {
- let (ffi_array, _) = arrow_array::ffi::to_ffi(&array.to_data())?;
+ let (ffi_array, ffi_schema) =
arrow_array::ffi::to_ffi(&array.to_data())?;
let refine_fn = self.inner.refiner.refine.unwrap();
let mut new_len: u32 = 0;
@@ -473,6 +466,7 @@ impl Refiner {
|| {
refine_fn(
&self.inner.refiner as *const _ as *mut _,
+ &ffi_schema as *const _ as *mut _,
&ffi_array as *const _ as *mut _,
predicate.as_c_uint(),
build_indices.as_mut_ptr(),