-
Notifications
You must be signed in to change notification settings - Fork 3
Add adapt #110
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?
Add adapt #110
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -47,6 +47,7 @@ ClimaComms.AbstractGraphContext | |||||
| ClimaComms.context | ||||||
| ClimaComms.graph_context | ||||||
| Adapt.adapt_structure(::Type{<:AbstractArray}, ::ClimaComms.AbstractCommsContext) | ||||||
| Adapt.adapt(::ClimaComms.AbstractDevice, ::Any) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Correct API documentation to match implementation The documentation currently shows -Adapt.adapt(::ClimaComms.AbstractDevice, ::Any)
+adapt(::ClimaComms.AbstractDevice, ::Any)📝 Committable suggestion
Suggested change
|
||||||
| ``` | ||||||
|
|
||||||
| ## Logging | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ Adapt.adapt_structure(Array, ClimaComms.context(ClimaComms.CUDADevice())) -> Cli | |
|
|
||
| !!! note | ||
| By default, adapting to `Array` creates a `CPUSingleThreaded` device, and | ||
| there is currently no way to conver to a CPUMultiThreaded device. | ||
| there is currently no way to convert to a CPUMultiThreaded device. | ||
| """ | ||
| Adapt.adapt_structure(to::Type{<:AbstractArray}, ctx::AbstractCommsContext) = | ||
| context(Adapt.adapt(to, device(ctx))) | ||
|
|
@@ -31,7 +31,26 @@ Adapt.adapt_structure(Array, ClimaComms.CUDADevice()) -> ClimaComms.CPUSingleThr | |
|
|
||
| !!! note | ||
| By default, adapting to `Array` creates a `CPUSingleThreaded` device, and | ||
| there is currently no way to conver to a CPUMultiThreaded device. | ||
| there is currently no way to convert to a CPUMultiThreaded device. | ||
| """ | ||
| Adapt.adapt_structure(::Type{<:AbstractArray}, device::AbstractDevice) = | ||
| CPUSingleThreaded() | ||
|
|
||
|
|
||
| """ | ||
| adapt(device::AbstractDevice, x) | ||
|
|
||
| Adapt an object `x` to be compatible with the specified `device`. | ||
| """ | ||
| function adapt(device::AbstractDevice, x) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @CodeRabbit generate a docstring for this function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Sbozzolo Here's a docstring for the """
adapt(device::AbstractDevice, x)
Adapt an object `x` to be compatible with the specified `device`. This is a convenience method
that internally calls `adapt(array_type(device), x)`.
# Arguments
- `device`: The target device to adapt the object for
- `x`: The object to be adapted
# Returns
The adapted object compatible with the specified device
# Example
```julia
# Adapt an array to be compatible with CUDA device
cuda_array = adapt(CUDADevice(), my_array)
# Adapt an array to be compatible with CPU
cpu_array = adapt(CPUSingleThreaded(), my_cuda_array)"""
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @CodeRabbit add unit tests for this function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainThe project has a test directory with several files including Now let me look at the actual implementation of the devices and CUDA support: I need to understand better how arrays are adapted and check if there's existing test infrastructure for CUDA: Let me check if there are any existing test files specifically for I see there are references to Let's examine the entire test setup to understand how I should structure the unit tests: Based on the exploration so far, I need to understand the available device types better to write appropriate tests: Let's see if we can find how the Before writing the tests, I should have a better understanding of how Let me check if there's a specific test file for the adapt functionality: Based on the information gathered, I'll now create appropriate unit tests for the @Sbozzolo Here are unit tests for the @testset "adapt" begin
# Test adapting arrays to CPU device
cpu_device = CPUSingleThreaded()
x_array = [1, 2, 3, 4]
# Test that adapt with a device forwards to adapt with array_type
@test adapt(cpu_device, x_array) == adapt(array_type(cpu_device), x_array)
@test adapt(cpu_device, x_array) == adapt(Array, x_array)
# Test with a more complex structure
complex_data = (a = [1, 2, 3], b = Dict(:x => [4, 5, 6]))
@test adapt(cpu_device, complex_data) == adapt(Array, complex_data)
# Test with scalar values (should be unchanged)
@test adapt(cpu_device, 42) == 42
@test adapt(cpu_device, "string") == "string"
# If CUDA support is available, test with CUDA device
if ClimaCommsCUDA !== nothing
cuda_device = CUDADevice()
# Create a CPU array and adapt it to CUDA
cpu_array = [1.0, 2.0, 3.0, 4.0]
cuda_array = adapt(cuda_device, cpu_array)
# Verify it's now a CuArray
@test cuda_array isa CUDA.CuArray
@test Array(cuda_array) == cpu_array
# Test that our device-based adapt works the same as direct array_type adapt
@test cuda_array == adapt(array_type(cuda_device), cpu_array)
# Test adapting back to CPU
@test adapt(cpu_device, cuda_array) isa Array
@test adapt(cpu_device, cuda_array) == cpu_array
end
endThese tests verify that:
Add these tests to your existing test file, likely in 🏁 Script executed: Length of output: 12765 🏁 Script executed: Length of output: 11010 🏁 Script executed: Length of output: 8109 🏁 Script executed: Length of output: 1683 🏁 Script executed: Length of output: 54 🏁 Script executed: Length of output: 1398 🏁 Script executed: Length of output: 8137 🏁 Script executed: Length of output: 8633 🏁 Script executed: Length of output: 467 🏁 Script executed: Length of output: 1276 🏁 Script executed: Length of output: 95 @Sbozzolo Here are unit tests for the new @testset "adapt with device" begin
# Test with CPU device
cpu_device = CPUSingleThreaded()
# Test with simple arrays
x_array = [1, 2, 3, 4]
# Test that adapt(device, x) correctly forwards to adapt(array_type(device), x)
@test adapt(cpu_device, x_array) == adapt(array_type(cpu_device), x_array)
@test adapt(cpu_device, x_array) == adapt(Array, x_array)
# Test with nested structures
nested_data = (a = [1, 2, 3], b = Dict(:x => [4, 5, 6]))
@test adapt(cpu_device, nested_data) == adapt(Array, nested_data)
# Test with scalar values (should remain unchanged)
@test adapt(cpu_device, 42) == 42
@test adapt(cpu_device, "test") == "test"
# Test with CUDA device if available
@static if isdefined(ClimaComms, :ClimaCommsCUDAExt)
cuda_device = CUDADevice()
# Create a test array and adapt it to CUDA
cpu_array = [1.0, 2.0, 3.0, 4.0]
cuda_array = adapt(cuda_device, cpu_array)
# Verify that the device-based adapt produces the same result as array_type-based adapt
@test cuda_array == adapt(array_type(cuda_device), cpu_array)
@test cuda_array isa CUDA.CuArray
# Test converting back to CPU
@test adapt(cpu_device, cuda_array) isa Array
@test Array(adapt(cpu_device, cuda_array)) == cpu_array
# Test with mixed data types
mixed_data = (cpu = [1.0, 2.0], cuda = cuda_array)
adapted_mixed = adapt(cpu_device, mixed_data)
@test adapted_mixed.cpu isa Array
@test adapted_mixed.cuda isa Array
end
endThese tests should be added to the existing The tests verify that:
|
||
| return Adapt.adapt(array_type(device), x) | ||
| end | ||
|
Comment on lines
+40
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainEnsure the adapt function is exported The implementation of the 🏁 Script executed: #!/bin/bash
# Check if the adapt function is exported in ClimaComms.jl
echo "Checking if adapt is exported in the module..."
if grep -q "export.*adapt" src/ClimaComms.jl; then
echo "✅ The adapt function is exported"
grep -n "export.*adapt" src/ClimaComms.jl
else
echo "❌ The adapt function is not exported"
echo "Suggested addition to src/ClimaComms.jl:"
echo "export adapt"
fiLength of output: 355 Action Required: Export the adapt function from ClimaComms.jl The implementation of the
Please update the module accordingly to allow the direct usage of |
||
|
|
||
| """ | ||
| adapt(device::AbstractCommsContext, x) | ||
|
|
||
| Adapt an object `x` to be compatible with the specified `context`. | ||
| """ | ||
| function adapt(context::AbstractCommsContext, x) | ||
| return Adapt.adapt(array_type(device(context)), x) | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import ClimaComms | ||
| import Adapt: adapt | ||
|
|
||
| @testset "Adapt" begin | ||
| # Test with CPU device | ||
| cpu_device = ClimaComms.CPUSingleThreaded() | ||
|
|
||
| # Test with simple arrays | ||
| x_array = [1, 2, 3, 4] | ||
|
|
||
| # Test that adapt(device, x) correctly forwards to adapt(array_type(device), x) | ||
| @test adapt(cpu_device, x_array) == | ||
| adapt(ClimaComms.array_type(cpu_device), x_array) | ||
| @test adapt(cpu_device, x_array) == adapt(Array, x_array) | ||
| @test adapt(ClimaComms.SingletonCommsContext(cpu_device), x_array) == | ||
| adapt(cpu_device, x_array) | ||
|
|
||
| # Test with nested structures | ||
| nested_data = (a = [1, 2, 3], b = Dict(:x => [4, 5, 6])) | ||
| @test adapt(cpu_device, nested_data) == adapt(Array, nested_data) | ||
|
|
||
| # Test with scalar values (should remain unchanged) | ||
| @test adapt(cpu_device, 42) == 42 | ||
| @test adapt(cpu_device, "test") == "test" | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -260,3 +260,7 @@ end | |
| @testset "Logging" begin | ||
| include("logging.jl") | ||
| end | ||
|
|
||
| @testset "Adapt" begin | ||
| include("adapt.jl") | ||
| end | ||
|
Comment on lines
+264
to
+266
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainDouble check test file name There are now two different test sections with the same name "Adapt" (line 232 and line 264). The existing test set at line 232 already tests 🏁 Script executed: #!/bin/bash
# Check the content of the adapt.jl test file
if [ -f "test/adapt.jl" ]; then
echo "✅ test/adapt.jl exists. Content:"
cat test/adapt.jl
else
echo "❌ test/adapt.jl does not exist"
fiLength of output: 985 Double-check duplicate test set names in tests It appears that there are two test sets named "Adapt": one defined at line 232 in
|
||
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.
💡 Verification agent
🧩 Analysis chain
Well-documented release note for the adapt function
The release note clearly explains the purpose of adding the
adaptfunction and its benefit for downstream packages. This documentation helps users understand the significance of this addition.However, the PR reference (PR 104) appears to be inconsistent with the current PR number (110).
🏁 Script executed:
Length of output: 1601
Action: Update PR reference in NEWS.md for the adapt feature
adaptfunction, which is well-described.