GRASS GSoC 2026 Parallelizing r.proj and Raster Processing Modules in GRASS

From GRASS-Wiki
Jump to navigation Jump to search
Student Name Kaushik Raja
Organization NumFOCUS
Mentor Name Huidae Cho, Anna Petrasova, Vaclav Petras
GitHub Fork View Repo
LinkedIn Profile View LinkedIn

Abstract

r.proj is one of the most commonly used modules in GRASS. It reprojects raster maps between coordinate systems. It has always been single threaded, so on modern multi core hardware most CPU cores sit idle and large reprojections take longer than they need to.

This project parallelizes r.proj and r.param.scale using OpenMP, with r.geomorphon planned as a third module. The two main obstacles are memory and the PROJ library. A naive parallel version holds the entire input map in RAM, which does not scale to large maps, and PROJ transformation objects cannot be shared between threads. The approach here processes the output map in horizontal bands sized to stay under a user controlled memory cap. For strongly tilted projections where even a single row of output needs more input than the cap allows, each band is further split into smaller column sections until every piece fits. Reading the input and computing the reprojection both run in parallel, with each thread using its own file descriptor and its own PROJ context, while the output is still written in row order so the result is exactly identical to the serial module.

r.param.scale, a terrain analysis module, was parallelized with the same memory bounded idea. Its sequential sliding window was replaced with a two level band and chunk design that honors the memory option. During that work a long standing data race was found in the GRASS math library and fixed. Together these changes give future GRASS contributors a reusable pattern for parallelizing raster modules under a memory constraint.

Project Scope

  1. Parallelize r.proj with a memory bounded band design and a user controlled memory option
  2. Split bands into column sections for tilted projections that do not fit the memory cap at full width
  3. Give each thread its own PROJ context through new gproj library functions
  4. Parallelize input reading with per thread file descriptors
  5. Parallelize r.param.scale with a band and chunk design that honors the memory option
  6. Find and fix the data race in G_ludcmp in the GRASS math library
  7. Verify every parallel version produces output exactly identical to the serial version
  8. Benchmark all modules across thread counts
  9. Parallelize r.geomorphon as a third module
  10. Document all parallelized modules

Timeline

Period Timeline Tasks Status
Community Bonding Period May 1 - May 25
  1. Thread safety audit of gprojects library calls
  2. Study readcell.c internals
  3. Set up benchmarking infrastructure
  4. Source audit of remaining modules
  5. Finalize dev environment
  6. Confirm benchmarks are reproducible
  7. Agree on implementation details with mentors
Done
Official Coding Period May 25 - June 8
  1. Build r.proj proof of concept with RAM buffer and per thread PROJ contexts (PR #7185)
  2. Benchmark RAM buffer approach against tile cache approach
  3. Add user controlled memory option
  4. Build first r.param.scale parallel draft (PR #7236)
  5. Rule out a suspected Mac OpenMP bug, traced to benchmark setup
Done
June 9 - June 22
  1. Redesign r.param.scale from a single strip into a two level band and chunk structure that honors the memory option, modeled on r.neighbors (PR #7440)
  2. Give each thread its own input access so threads no longer share one reader
  3. Measure 4.6x speedup at 8 threads, up from 2.7x before the redesign, with output identical to the serial module
  4. Trace a scaling dip to thread load imbalance using per thread timing, correlation of 0.99 between imbalance and slow runs, ruling out a CPU frequency explanation
  5. Find a data race in G_ludcmp in the GRASS math library affecting every parallel caller, prove it with ThreadSanitizer and a controlled toggle experiment, report it (issue #7539)
  6. Fix the race and verify with ThreadSanitizer showing 14 race reports before and 0 after, repeated test runs going from 10 failures in 100 to 0 in 20, and a 40 configuration bit identical output comparison
  7. Check every caller of the fixed function at runtime to confirm safety for dependent modules
  8. Debug CI failures across platforms including CMake PROJ linkage and unguarded OpenMP timer calls, resolve a git branch divergence, unskip and pass the pytest suites on Python 3.10 and 3.13, pass all 26 checks, mark PR #7440 ready for review
Done
June 23 - July 6
  1. Design and build the band based r.proj (PR #7627)
  2. Size each band by projecting its edges back to the input to find the rows it needs
  3. Cut peak memory from 763 MB to 130 MB with identical output
  4. Measure 2.9x total and 5.2x compute speedup at 8 threads on a 105 million cell map
  5. Answer two rounds of mentor review
Done
July 7 - July 11
  1. Submit midterm evaluation
  2. Fix two CI failures, a missing PROJ dependency in the CMake build and OpenMP timer calls breaking the no OpenMP build
  3. Parallelize input reading with per thread file descriptors, 1.9x faster reads, about 3.0x total
  4. Move per thread PROJ context handling into the gproj library as new API functions at maintainer request
  5. Measure which projections need column splitting with a standalone footprint tool
  6. Split bands into column sections so tilted reprojections that failed under the memory cap now complete, verified identical on three projections
  7. Cut the section sizing search from 54 seconds to 2.6 seconds
  8. Benchmark everything and present results to mentors
Done
July 20 - August 3
  1. Speed up the section sizing search further by reusing neighboring band results
  2. Test whether pole covering sections complete when given more memory
  3. Build the tile cache fallback for pole covering sections
  4. Address code review feedback on PR #7627
In progress
August 4 - August 11
  1. Parallelize bilinear, bicubic and lanczos interpolation in the band design
  2. r.geomorphon parallelization
August 12 - August 18
  1. Pre-commit fixes, manual pages, final PR polish
  2. Blog post for OSGeo Planet
Final Week August 19 - August 26
  1. Submit final evaluation

Reports

Community Bonding Period

Coding Period

Log of Pull Requests

  • PR #7440 - r.param.scale parallelization and G_ludcmp race fix, ready for review
  • PR #7627 - r.proj parallelization with memory bounded bands, in review
  • Issue #7539 - G_ludcmp data race report
  • PR #7185 - r.proj proof of concept, closed in favor of #7627
  • PR #7236 - r.param.scale proof of concept, closed in favor of #7440