1
1
using DynamicExpressions
2
+ using DynamicExpressions. AsArrayModule: as_array
2
3
using CUDA
3
4
using Random
4
5
@@ -10,55 +11,116 @@ include("tree_gen_utils.jl")
10
11
safe_sin (x) = isfinite (x) ? sin (x) : convert (eltype (x), NaN )
11
12
safe_cos (x) = isfinite (x) ? cos (x) : convert (eltype (x), NaN )
12
13
13
- let
14
- operators = OperatorEnum (;
15
- binary_operators= [+ , - , * , / ], unary_operators= [safe_sin, safe_cos]
16
- )
17
- x1, x2, x3 = (i -> Node (Float64; feature= i)). (1 : 3 )
18
-
19
- for T in (Float32, Float64, ComplexF64), ntrees in (1 , 2 , 3 ), seed in 0 : 10
20
- Random. seed! (seed)
21
-
22
- nrow = rand (10 : 30 )
23
- nnodes = rand (10 : 25 , ntrees)
24
- use_tuple = rand (Bool)
25
-
26
- buffer = rand (Bool) ? ones (Int32, 8 , sum (nnodes)) : nothing
27
- gpu_buffer = rand (Bool) ? FakeCuArray (ones (Int32, 8 , sum (nnodes))) : nothing
28
- gpu_workspace = rand (Bool) ? FakeCuArray (ones (T, nrow + 1 , sum (nnodes))) : nothing
29
-
30
- trees = ntuple (i -> gen_random_tree_fixed_size (nnodes[i], operators, 3 , T), ntrees)
31
- trees = use_tuple ? trees : collect (trees)
32
- X = randn (T, 3 , nrow)
33
- if ntrees > 1
34
- y, completed = @inferred eval_tree_array (trees, X, operators)
35
- gpu_y, gpu_completed = @inferred eval_tree_array (
36
- trees, FakeCuArray (X), operators; buffer, gpu_workspace, gpu_buffer
14
+ @testset " Random evals" begin
15
+ let
16
+ operators = OperatorEnum (;
17
+ binary_operators= [+ , - , * , / ], unary_operators= [safe_sin, safe_cos]
18
+ )
19
+ x1, x2, x3 = (i -> Node (Float64; feature= i)). (1 : 3 )
20
+
21
+ for T in (Float32, Float64, ComplexF64), ntrees in (1 , 2 , 3 ), seed in 0 : 10
22
+ Random. seed! (seed)
23
+
24
+ nrow = rand (10 : 30 )
25
+ nnodes = rand (10 : 25 , ntrees)
26
+ use_tuple = rand (Bool)
27
+
28
+ buffer = rand (Bool) ? ones (Int32, 8 , sum (nnodes)) : nothing
29
+ gpu_buffer = rand (Bool) ? FakeCuArray (ones (Int32, 8 , sum (nnodes))) : nothing
30
+ gpu_workspace =
31
+ rand (Bool) ? FakeCuArray (ones (T, nrow + 1 , sum (nnodes))) : nothing
32
+
33
+ trees = ntuple (
34
+ i -> gen_random_tree_fixed_size (nnodes[i], operators, 3 , T), ntrees
37
35
)
36
+ trees = use_tuple ? trees : collect (trees)
37
+ X = randn (T, 3 , nrow)
38
+ if ntrees > 1
39
+ y, completed = @inferred eval_tree_array (trees, X, operators)
40
+ gpu_y, gpu_completed = @inferred eval_tree_array (
41
+ trees, FakeCuArray (X), operators; buffer, gpu_workspace, gpu_buffer
42
+ )
38
43
39
- # Should give same result either way
40
- for i in eachindex (completed, gpu_completed)
41
- if completed[i]
42
- @test y[i] ≈ gpu_y[i]
44
+ # Should give same result either way
45
+ for i in eachindex (completed, gpu_completed)
46
+ if completed[i]
47
+ @test y[i] ≈ gpu_y[i]
48
+ end
43
49
end
44
- end
45
50
46
- # Should return same type as input
47
- if use_tuple
48
- @test y isa Tuple
49
- @test gpu_y isa Tuple
51
+ # Should return same type as input
52
+ if use_tuple
53
+ @test y isa Tuple
54
+ @test gpu_y isa Tuple
55
+ else
56
+ @test y isa Vector
57
+ @test gpu_y isa Vector
58
+ end
50
59
else
51
- @test y isa Vector
52
- @test gpu_y isa Vector
53
- end
54
- else
55
- y, completed = @inferred eval_tree_array (only (trees), X, operators)
56
- gpu_y, gpu_completed = @inferred eval_tree_array (
57
- only (trees), FakeCuArray (X), operators
58
- )
59
- if completed
60
- @test y ≈ gpu_y
60
+ y, completed = @inferred eval_tree_array (only (trees), X, operators)
61
+ gpu_y, gpu_completed = @inferred eval_tree_array (
62
+ only (trees), FakeCuArray (X), operators
63
+ )
64
+ if completed
65
+ @test y ≈ gpu_y
66
+ end
61
67
end
62
68
end
63
69
end
64
70
end
71
+
72
+ @testset " Evaluation on pre-computed buffers" begin
73
+ let
74
+ operators = OperatorEnum (;
75
+ binary_operators= [+ , - , * , / ], unary_operators= [sin, cos]
76
+ )
77
+ x1, x2, x3 = (i -> Node (Float64; feature= i)). (1 : 3 )
78
+ Random. seed! (0 )
79
+ tree = sin (x1 * 3.1 - x3 * 0.9 + 0.2 ) * x2 - x3 * x3 * 1.5
80
+ X = randn (Float64, 3 , 100 )
81
+
82
+ y1, _ = eval_tree_array (tree, X, operators)
83
+ y2, _ = eval_tree_array (tree, FakeCuArray (X), operators)
84
+
85
+ @test y1 ≈ y2
86
+
87
+ (; val, roots, buffer, num_nodes, num_launches) = as_array (Int32, tree)
88
+ gpu_buffer = FakeCuArray (buffer)
89
+ gpu_workspace = FakeCuArray (zeros (Float64, 101 , 50 ))
90
+ copyto! ((@view gpu_workspace[end , :]), val)
91
+
92
+ # Now, with all buffers:
93
+ y3, _ = eval_tree_array (
94
+ tree,
95
+ FakeCuArray (X),
96
+ operators;
97
+ gpu_workspace,
98
+ gpu_buffer,
99
+ roots,
100
+ num_nodes,
101
+ num_launches,
102
+ update_buffers= Val (false ),
103
+ )
104
+ @test y1 ≈ y3
105
+
106
+ # Should be able to shift some of the values in this buffer:
107
+ i = findfirst (gpu_workspace[end , :] .== 0.9 )
108
+ gpu_workspace[end , i] = 0.8
109
+
110
+ # And get the updated results:
111
+ tree_prime = sin (x1 * 3.1 - x3 * 0.8 + 0.2 ) * x2 - x3 * x3 * 1.5
112
+ y1_prime, _ = eval_tree_array (tree_prime, X, operators)
113
+ y3_prime, _ = eval_tree_array (
114
+ x1, # Doesn't matter what we put here
115
+ FakeCuArray (X),
116
+ operators;
117
+ gpu_workspace,
118
+ gpu_buffer,
119
+ roots,
120
+ num_nodes,
121
+ num_launches,
122
+ update_buffers= Val (false ),
123
+ )
124
+ @test y1_prime ≈ y3_prime
125
+ end
126
+ end
0 commit comments