-
Notifications
You must be signed in to change notification settings - Fork 40
feat(rust/sedona-spatial-join-gpu): Add GPU-accelerated spatial join support #465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat(rust/sedona-spatial-join-gpu): Add GPU-accelerated spatial join support #465
Conversation
…support This commit introduces GPU-accelerated spatial join capabilities to SedonaDB, enabling significant performance improvements for large-scale spatial join operations. Key changes: - Add new `sedona-spatial-join-gpu` crate that provides GPU-accelerated spatial join execution using CUDA via the `sedona-libgpuspatial` library. - Implement `GpuSpatialJoinExec` execution plan with build/probe phases that efficiently handles partitioned data by sharing build-side data across probes. - Add GPU backend abstraction (`GpuBackend`) for geometry data transfer and spatial predicate evaluation on GPU. - Extend the spatial join optimizer to automatically select GPU execution when available and beneficial, with configurable thresholds and fallback to CPU. - Add configuration options in `SedonaOptions` for GPU spatial join settings including enable/disable, row thresholds, and CPU fallback behavior. - Include comprehensive benchmarks and functional tests for GPU spatial join correctness validation against CPU reference implementations.
…re/gpu-spatial-join-new
…t/sedona-db into feature/gpu-spatial-join-new
|
Will merge the patch to fix the failing example build once this is merged - #486 |
paleolimbot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on this!
In addition to specific comments, I'm concerned about the proliferation of conditional compilation (partiuclarly within sedona-spatial-join, which is a rather important part of our engine to keep clean).
At a high level what sedona-spatial-join-gpu is doing is more like sedona-spatial-join-extension: it provides a simpler (FFI-friendly) mechanism to inject a join operator without dealing with the DataFusion-y details. I think most of the conditional compilation/dead code/unused/ignore directives could be avoided if we add a CPU join extension and use that for all the tests. The GPU extension itself would then be a runtime implementation detail (eventually loaded at runtime via FFI).
| // Helper execution plan that returns a single pre-loaded batch | ||
| struct SingleBatchExec { | ||
| schema: Arc<Schema>, | ||
| batch: RecordBatch, | ||
| props: datafusion::physical_plan::PlanProperties, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems very similar to SessionContext::register_batch() and is a lot of lines of code. Do we need this?
| /// Generate random points within a bounding box | ||
| fn generate_random_points(count: usize) -> Vec<String> { | ||
| use rand::Rng; | ||
| let mut rng = rand::thread_rng(); | ||
| (0..count) | ||
| .map(|_| { | ||
| let x: f64 = rng.gen_range(-180.0..180.0); | ||
| let y: f64 = rng.gen_range(-90.0..90.0); | ||
| format!("POINT ({} {})", x, y) | ||
| }) | ||
| .collect() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a random geometry generator in sedona-testing (that is used in the non-GPU join tests and elsewhere) that I think we should be using here!
| sedona_libgpuspatial::SpatialPredicate::Intersects, | ||
| ), | ||
| device_id: 0, | ||
| batch_size: 8192, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be Option<usize> so that it can default to the datafusion.batch_size setting?
| let properties = PlanProperties::new( | ||
| eq_props, | ||
| partitioning, | ||
| EmissionType::Final, // GPU join produces all results at once |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking that this is correct (I thought that because one side is streaming the output might be incremental?)
| /// GPU backend for spatial operations | ||
| #[allow(dead_code)] | ||
| pub struct GpuBackend { | ||
| device_id: i32, | ||
| gpu_context: Option<GpuSpatialContext>, | ||
| } | ||
|
|
||
| #[allow(dead_code)] | ||
| impl GpuBackend { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these dead code markers be removed?
| let kernels = scalar_kernels(); | ||
| let sedona_type = SedonaType::Wkb(Edges::Planar, lnglat()); | ||
|
|
||
| let _cpu_testers: std::collections::HashMap<&str, ScalarUdfTester> = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this variable is not used / can we do this using a for loop to avoid this indirection?
|
|
||
| #[cfg(feature = "gpu")] | ||
| #[tokio::test] | ||
| #[ignore] // Requires GPU hardware |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to figure out a way to not ignore tests in this repo (in this case I think these tests shouldn't exist if the gpu feature isn't enabled so we shouldn't need the ignore it?)
| SpatialRelationType::Intersects => LibGpuPred::Intersects, | ||
| SpatialRelationType::Contains => LibGpuPred::Contains, | ||
| SpatialRelationType::Covers => LibGpuPred::Covers, | ||
| SpatialRelationType::Within => LibGpuPred::Within, | ||
| SpatialRelationType::CoveredBy => LibGpuPred::CoveredBy, | ||
| SpatialRelationType::Touches => LibGpuPred::Touches, | ||
| SpatialRelationType::Equals => LibGpuPred::Equals, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move SpatialRelationType to sedona-geometry or sedona-common to avoid two copies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git submodule update --recursive should remove this diff
| default = ["mimalloc"] | ||
| mimalloc = ["dep:mimalloc", "dep:libmimalloc-sys"] | ||
| s2geography = ["sedona/s2geography"] | ||
| gpu = ["sedona/gpu"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we don't have any tests in Python for this feature I suggest leaving this out for now (a follow-up PR could add Python support + a test)
…re/gpu-spatial-join-new
This commit introduces GPU-accelerated spatial join capabilities to SedonaDB, enabling significant performance improvements for large-scale spatial join operations.
Key changes:
sedona-spatial-join-gpucrate that provides GPU-accelerated spatial join execution using CUDA via thesedona-libgpuspatiallibrary.GpuSpatialJoinExecexecution plan with build/probe phases that efficiently handles partitioned data by sharing build-side data across probes.GpuBackend) for geometry data transfer and spatial predicate evaluation on GPU.SedonaOptionsfor GPU spatial join settings including enable/disable, row thresholds, and CPU fallback behavior.