Skip to content

Make CUDA a weak dependency using package extensions#80

Merged
zsoerenm merged 20 commits into
masterfrom
ss/cuda-weak-dependency
Nov 19, 2025
Merged

Make CUDA a weak dependency using package extensions#80
zsoerenm merged 20 commits into
masterfrom
ss/cuda-weak-dependency

Conversation

@zsoerenm

Copy link
Copy Markdown
Member

Make CUDA a weak dependency using package extensions

Converts CUDA from a hard dependency to a weak dependency using Julia's package extension system (Julia 1.10+). This allows CPU-only users to install and use Tracking.jl without downloading CUDA, while maintaining full GPU functionality for users who need it.

Changes

Package Configuration

  • Project.toml: Moved CUDA from [deps] to [weakdeps] and added [extensions] section
  • Extension created: TrackingCUDAExt activates automatically when CUDA is loaded

Code Organization

  • GPU code isolated: All GPU implementation moved to ext/TrackingCUDAExt/
    • Extension entry point: ext/TrackingCUDAExt/TrackingCUDAExt.jl
    • GPU implementation: ext/TrackingCUDAExt/downconvert_and_correlate_gpu.jl (346 lines)
  • Main module cleaned: Removed all CUDA imports and GPU-specific code from src/Tracking.jl
  • Type exports added: Exported abstract types and helper functions needed by the extension

Testing

  • Main tests: Removed CUDA dependency from test/Project.toml - all 100,000+ tests now run without CUDA
  • GPU tests: Moved to ext/TrackingCUDAExt/test/ (222 lines) - run separately with CUDA available
  • Test isolation: GPU tests skip gracefully when CUDA is not functional

Documentation

  • README.md: Added GPU Support section explaining:
    • How to activate GPU functionality (using CUDA)
    • How to access GPU types via Base.get_extension(Tracking, :TrackingCUDAExt)

CI/CD

  • Buildkite pipeline: Updated to run GPU extension tests on CUDA-enabled agents
  • No breaking changes: Existing GPU users just need to add using CUDA to their code

Usage

CPU-only (no CUDA required)

using Tracking
# All CPU functionality available
correlator = CPUDownconvertAndCorrelator(...)

With GPU support

using Tracking
using CUDA  # Activates GPU extension

# Access GPU types via extension
ext = Base.get_extension(Tracking, :TrackingCUDAExt)
gpu_correlator = ext.GPUDownconvertAndCorrelator(...)

Benefits

  • Reduced installation size: CPU-only users don't download CUDA dependencies
  • Faster install times: No CUDA precompilation for users who don't need it
  • Cleaner architecture: GPU code properly isolated in extension
  • Maintains compatibility: GPU functionality fully preserved for those who need it

zsoerenm and others added 13 commits October 4, 2025 11:14
📦 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Move CUDA from [deps] to [weakdeps]
- Add TrackingCUDAExt extension

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove 'using CUDA' statement
- Remove GPU file inclusion
- Remove GPU type exports (moved to extension)
- Keep abstract type for extension dispatch

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Extension activates when CUDA is loaded and provides GPU types.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
All CUDA-specific code now lives in TrackingCUDAExt extension.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Export the following types and functions required by TrackingCUDAExt:

Types:
- AbstractCorrelator
- AbstractDownconvertAndCorrelator
- MultipleSystemType
- MultipleSystemSatsState

Functions:
- get_num_accumulators
- get_correlator_sample_shifts
- calc_signal_samples_to_integrate
- update
- get_code_frequency
- get_code_length
- get_codes
- get_modulation
- get_secondary_code
- update_accumulator

This resolves the UndefVarError: AbstractCorrelator not defined error
that prevented the CUDA extension from loading.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Declare global variables in Tracking module for GPU types
- Use __init__ function in TrackingCUDAExt to assign types to parent module
- GPU types (GPUSatDownconvertAndCorrelator, GPUSystemDownconvertAndCorrelator,
  GPUDownconvertAndCorrelator) and convert_code_to_texture_memory function
  are now accessible via Tracking.* when CUDA is loaded
- Extension exports don't propagate to parent module, so explicit assignment
  via @eval in __init__ is required

Fixes issue where GPU types existed in TrackingCUDAExt but were not
accessible in the Tracking namespace despite export statements.
…ngCUDAExt

- Remove __init__() from extension (user requested to avoid it)
- Remove global declarations from main module
- Update extension to use simple export pattern
- Update test imports to use Tracking.TrackingCUDAExt.GPUDownconvertAndCorrelator
- GPU types now accessible as Tracking.TrackingCUDAExt.TypeName

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Note that GPU features require explicit CUDA loading
- Add GPU support section with usage example

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Created ext/TrackingCUDAExt/test/runtests.jl with GPU-specific tests
- Extracted GPU downconvert_and_correlate tests from test/downconvert_and_correlate.jl
- Extracted "Track multiple signals with GPU" test from test/track.jl
- Removed CUDA imports and GPUDownconvertAndCorrelator imports from main test files
- Updated test/Project.toml to remove CUDA and Pkg dependencies
- Main tests now run without CUDA dependency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated extension tests to properly access GPU types using Base.get_extension
instead of direct module reference, which is the correct pattern for Julia
package extensions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated the CI pipeline to test GPU functionality from the extension tests
instead of the main test suite, since GPU tests have been moved to
ext/TrackingCUDAExt/test/.

Changes:
- Run GPU extension tests directly using the extension test environment
- First instantiate the extension test dependencies
- Then execute the GPU test suite
- Removed standard julia-test plugin in favor of custom commands

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 19, 2025

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
master bd0f2e1... master / bd0f2e1...
downconvert and correlate/CPU/Float32 2.9 ± 0.12 μs 2.84 ± 0.19 μs 1.02 ± 0.08
downconvert and correlate/CPU/Float64 3.15 ± 0.12 μs 3.11 ± 0.14 μs 1.01 ± 0.059
downconvert and correlate/CPU/Int16 2.83 ± 0.13 μs 2.81 ± 0.11 μs 1.01 ± 0.061
downconvert and correlate/CPU/Int32 2.94 ± 0.093 μs 2.91 ± 0.12 μs 1.01 ± 0.052
track/Float32 3.34 ± 0.17 μs 3.18 ± 0.25 μs 1.05 ± 0.099
time_to_load 4.66 ± 0.034 s 0.904 ± 0.012 s 5.16 ± 0.076
Memory benchmarks
master bd0f2e1... master / bd0f2e1...
downconvert and correlate/CPU/Float32 2 allocs: 0.359 kB 2 allocs: 0.359 kB 1
downconvert and correlate/CPU/Float64 2 allocs: 0.359 kB 2 allocs: 0.359 kB 1
downconvert and correlate/CPU/Int16 2 allocs: 0.359 kB 2 allocs: 0.359 kB 1
downconvert and correlate/CPU/Int32 2 allocs: 0.359 kB 2 allocs: 0.359 kB 1
track/Float32 12 allocs: 1.64 kB 12 allocs: 1.64 kB 1
time_to_load 0.149 k allocs: 11.1 kB 0.145 k allocs: 11 kB 1.02

zsoerenm and others added 3 commits November 19, 2025 12:24
The CI was failing because Pkg.instantiate() alone doesn't resolve the
local Tracking package's dependencies (like Statistics). Adding
Pkg.develop(PackageSpec(path=pwd())) before instantiate ensures all
transitive dependencies are properly resolved.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Extension test Manifest.toml files are environment-specific and should not be
tracked in git. Added pattern to .gitignore to exclude all extension test
Manifests. These files are regenerated by CI via Pkg.instantiate().

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removed .github/workflows/documenter.yml and docs/Project.toml which were
accidentally included in commit e119311. These files are not related to the
CUDA weak dependency implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@zsoerenm zsoerenm changed the title Ss/cuda weak dependency Make CUDA a weak dependency using package extensions Nov 19, 2025
Update README to show the standard Julia pattern for accessing extension
types via Base.get_extension(). This is the idiomatic approach that avoids
incremental compilation issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@zsoerenm

Copy link
Copy Markdown
Member Author
image

:)

@zsoerenm zsoerenm self-assigned this Nov 19, 2025
@zsoerenm
zsoerenm requested a review from siebc November 19, 2025 11:55
zsoerenm and others added 2 commits November 19, 2025 13:36
The extension needs to explicitly import downconvert_and_correlate and
downconvert_and_correlate! from the parent Tracking module in order to
add GPU-specific method implementations. Without this import, the GPU
methods are defined in the extension's namespace only and don't extend
the generic functions from Tracking, causing MethodError when calling
with GPU types.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add missing imports for get_num_samples (not exported) and update
(exported by both CUDA and Tracking) to resolve UndefVarError and
name conflict warning in the GPU extension.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

@siebc siebc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me!

@zsoerenm
zsoerenm enabled auto-merge (rebase) November 19, 2025 14:08
@zsoerenm
zsoerenm merged commit 90865cc into master Nov 19, 2025
6 checks passed
@zsoerenm
zsoerenm deleted the ss/cuda-weak-dependency branch November 19, 2025 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants