cumo 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +44 -2
- data/README.md +133 -0
- data/bench/cumo_sync_probe.rb +71 -8
- data/ext/cumo/cuda/cublas.c +0 -40
- data/ext/cumo/cuda/cudnn.c +48 -0
- data/ext/cumo/cuda/cudnn_impl.cpp +91 -62
- data/ext/cumo/cuda/runtime.c +3 -4
- data/ext/cumo/cumo.c +34 -0
- data/ext/cumo/extconf.rb +2 -0
- data/ext/cumo/include/cumo/cuda/cudnn.h +21 -2
- data/ext/cumo/include/cumo/cuda/cumo_thrust.hpp +1 -0
- data/ext/cumo/include/cumo/cuda/runtime.h +28 -0
- data/ext/cumo/include/cumo/intern.h +4 -1
- data/ext/cumo/include/cumo/narray.h +59 -3
- data/ext/cumo/include/cumo/template.h +35 -10
- data/ext/cumo/include/cumo/template_kernel.h +96 -0
- data/ext/cumo/include/cumo/types/bit.h +3 -0
- data/ext/cumo/include/cumo/types/bit_kernel.h +3 -0
- data/ext/cumo/include/cumo/types/complex_macro.h +2 -0
- data/ext/cumo/include/cumo/types/complex_macro_kernel.h +2 -0
- data/ext/cumo/include/cumo/types/float_macro.h +2 -0
- data/ext/cumo/include/cumo/types/float_macro_kernel.h +2 -0
- data/ext/cumo/include/cumo/types/half_def.h +129 -0
- data/ext/cumo/include/cumo/types/half_def_kernel.h +28 -0
- data/ext/cumo/include/cumo/types/half_macro.h +188 -0
- data/ext/cumo/include/cumo/types/half_macro_kernel.h +198 -0
- data/ext/cumo/include/cumo/types/hfloat.h +22 -0
- data/ext/cumo/include/cumo/types/hfloat_kernel.h +16 -0
- data/ext/cumo/include/cumo/types/real_accum.h +2 -0
- data/ext/cumo/include/cumo/types/real_accum_kernel.h +2 -0
- data/ext/cumo/include/cumo/types/robj_macro.h +3 -0
- data/ext/cumo/include/cumo/types/xint_macro.h +3 -0
- data/ext/cumo/include/cumo/types/xint_macro_kernel.h +2 -0
- data/ext/cumo/include/cumo.h +2 -2
- data/ext/cumo/narray/data.c +49 -174
- data/ext/cumo/narray/gen/def/bit.rb +2 -0
- data/ext/cumo/narray/gen/def/dcomplex.rb +2 -0
- data/ext/cumo/narray/gen/def/dfloat.rb +8 -0
- data/ext/cumo/narray/gen/def/hfloat.rb +47 -0
- data/ext/cumo/narray/gen/def/int16.rb +2 -0
- data/ext/cumo/narray/gen/def/int32.rb +2 -0
- data/ext/cumo/narray/gen/def/int64.rb +2 -0
- data/ext/cumo/narray/gen/def/int8.rb +2 -0
- data/ext/cumo/narray/gen/def/robject.rb +2 -0
- data/ext/cumo/narray/gen/def/scomplex.rb +2 -0
- data/ext/cumo/narray/gen/def/sfloat.rb +8 -0
- data/ext/cumo/narray/gen/def/uint16.rb +3 -1
- data/ext/cumo/narray/gen/def/uint32.rb +3 -1
- data/ext/cumo/narray/gen/def/uint64.rb +2 -0
- data/ext/cumo/narray/gen/def/uint8.rb +3 -1
- data/ext/cumo/narray/gen/erbpp2.rb +6 -0
- data/ext/cumo/narray/gen/spec.rb +1 -0
- data/ext/cumo/narray/gen/tmpl/accum.c +1 -1
- data/ext/cumo/narray/gen/tmpl/accum_arg.c +1 -1
- data/ext/cumo/narray/gen/tmpl/accum_arg_kernel.cu +5 -5
- data/ext/cumo/narray/gen/tmpl/accum_binary_kernel.cu +14 -1
- data/ext/cumo/narray/gen/tmpl/accum_index.c +1 -1
- data/ext/cumo/narray/gen/tmpl/accum_index_kernel.cu +5 -5
- data/ext/cumo/narray/gen/tmpl/alloc_func.c +4 -7
- data/ext/cumo/narray/gen/tmpl/allocate.c +1 -2
- data/ext/cumo/narray/gen/tmpl/aref_cpu.c +1 -1
- data/ext/cumo/narray/gen/tmpl/batch_norm.c +11 -23
- data/ext/cumo/narray/gen/tmpl/batch_norm_backward.c +12 -24
- data/ext/cumo/narray/gen/tmpl/binary_kernel.cu +69 -2
- data/ext/cumo/narray/gen/tmpl/clip.c +3 -3
- data/ext/cumo/narray/gen/tmpl/cond_unary.c +1 -1
- data/ext/cumo/narray/gen/tmpl/conv.c +11 -17
- data/ext/cumo/narray/gen/tmpl/conv_grad_w.c +11 -17
- data/ext/cumo/narray/gen/tmpl/conv_transpose.c +11 -17
- data/ext/cumo/narray/gen/tmpl/cum.c +24 -1
- data/ext/cumo/narray/gen/tmpl/cum_kernel.cu +29 -4
- data/ext/cumo/narray/gen/tmpl/each.c +2 -3
- data/ext/cumo/narray/gen/tmpl/each_with_index.c +5 -21
- data/ext/cumo/narray/gen/tmpl/extract_cpu.c +1 -1
- data/ext/cumo/narray/gen/tmpl/extract_data.c +1 -1
- data/ext/cumo/narray/gen/tmpl/fill.c +1 -1
- data/ext/cumo/narray/gen/tmpl/fixed_batch_norm.c +9 -21
- data/ext/cumo/narray/gen/tmpl/float_accum_kernel.cu +42 -37
- data/ext/cumo/narray/gen/tmpl/format.c +1 -1
- data/ext/cumo/narray/gen/tmpl/format_to_a.c +1 -1
- data/ext/cumo/narray/gen/tmpl/gemm.c +78 -27
- data/ext/cumo/narray/gen/tmpl/init_class.c +0 -7
- data/ext/cumo/narray/gen/tmpl/init_upcast.c +6 -0
- data/ext/cumo/narray/gen/tmpl/inspect.c +1 -1
- data/ext/cumo/narray/gen/tmpl/lib.c +11 -1
- data/ext/cumo/narray/gen/tmpl/map_with_index.c +7 -14
- data/ext/cumo/narray/gen/tmpl/median.c +9 -47
- data/ext/cumo/narray/gen/tmpl/minmax.c +1 -1
- data/ext/cumo/narray/gen/tmpl/poly.c +1 -1
- data/ext/cumo/narray/gen/tmpl/pooling_backward.c +2 -14
- data/ext/cumo/narray/gen/tmpl/pooling_forward.c +2 -14
- data/ext/cumo/narray/gen/tmpl/qsort.c +0 -1
- data/ext/cumo/narray/gen/tmpl/rand.c +20 -2
- data/ext/cumo/narray/gen/tmpl/rand_kernel.cu +13 -0
- data/ext/cumo/narray/gen/tmpl/rand_norm.c +4 -4
- data/ext/cumo/narray/gen/tmpl/rand_norm_kernel.cu +7 -5
- data/ext/cumo/narray/gen/tmpl/real_accum_kernel.cu +83 -97
- data/ext/cumo/narray/gen/tmpl/sort.c +1 -1
- data/ext/cumo/narray/gen/tmpl/sort_index.c +6 -3
- data/ext/cumo/narray/gen/tmpl/store_array.c +21 -22
- data/ext/cumo/narray/gen/tmpl/store_bit.c +1 -1
- data/ext/cumo/narray/gen/tmpl/store_from.c +1 -1
- data/ext/cumo/narray/gen/tmpl/store_from_kernel.cu +37 -2
- data/ext/cumo/narray/gen/tmpl/to_a.c +1 -1
- data/ext/cumo/narray/gen/tmpl/unary.c +20 -3
- data/ext/cumo/narray/gen/tmpl/unary2.c +1 -1
- data/ext/cumo/narray/gen/tmpl/unary_s.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/allocate.c +2 -3
- data/ext/cumo/narray/gen/tmpl_bit/aref_cpu.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/bit_count_cpu.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/each.c +2 -2
- data/ext/cumo/narray/gen/tmpl_bit/each_with_index.c +5 -20
- data/ext/cumo/narray/gen/tmpl_bit/extract_cpu.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/format.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/format_to_a.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/inspect.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/mask.c +38 -17
- data/ext/cumo/narray/gen/tmpl_bit/mask_kernel.cu +4 -4
- data/ext/cumo/narray/gen/tmpl_bit/store_array.c +10 -11
- data/ext/cumo/narray/gen/tmpl_bit/store_from.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/to_a.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/where.c +66 -13
- data/ext/cumo/narray/gen/tmpl_bit/where2.c +57 -20
- data/ext/cumo/narray/gen/tmpl_bit/where_kernel.cu +6 -6
- data/ext/cumo/narray/index.c +63 -18
- data/ext/cumo/narray/index_kernel.cu +15 -0
- data/ext/cumo/narray/math.c +2 -0
- data/ext/cumo/narray/narray.c +289 -183
- data/ext/cumo/narray/ndloop.c +91 -26
- data/ext/cumo/narray/sort_kernel.cu +39 -18
- data/ext/cumo/narray/struct.c +14 -17
- data/lib/cumo/cuda/cudnn.rb +1 -1
- data/lib/cumo/narray/extra.rb +11 -2
- data/test/bit_test.rb +147 -0
- data/test/cudnn_test.rb +132 -46
- data/test/extra_test.rb +1 -1
- data/test/hfloat_test.rb +717 -0
- data/test/math_test.rb +4 -1
- data/test/narray_alt_coverage_test.rb +7 -0
- data/test/narray_test.rb +1018 -11
- data/test/test_helper.rb +73 -0
- metadata +11 -1
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
#ifdef CUDNN_FOUND
|
|
2
2
|
|
|
3
|
-
<%
|
|
4
|
-
cudnn_dtype =
|
|
5
|
-
case type_name
|
|
6
|
-
when 'sfloat'
|
|
7
|
-
'CUDNN_DATA_FLOAT'
|
|
8
|
-
when 'dfloat'
|
|
9
|
-
'CUDNN_DATA_DOUBLE'
|
|
10
|
-
else
|
|
11
|
-
# CUDNN_DATA_HALF
|
|
12
|
-
raise 'not supported'
|
|
13
|
-
end
|
|
14
|
-
%>
|
|
15
3
|
|
|
16
4
|
// cover_all=true is not supported with CUDNN
|
|
17
5
|
// x.pooling_forward(mode, kernel_size, stride: 1, pad: 0, y: nil)
|
|
@@ -25,8 +13,8 @@ static VALUE
|
|
|
25
13
|
cudnnDataType_t cudnn_dtype = <%= cudnn_dtype %>;
|
|
26
14
|
cudnnStatus_t status = 0;
|
|
27
15
|
cudnnHandle_t handle = 0;
|
|
28
|
-
|
|
29
|
-
|
|
16
|
+
<%=cudnn_scalar_t%> alpha = 1;
|
|
17
|
+
<%=cudnn_scalar_t%> beta = 0;
|
|
30
18
|
|
|
31
19
|
VALUE x=self, mode, kernel_size, stride, pad, y;
|
|
32
20
|
VALUE kw_hash = Qnil;
|
|
@@ -58,6 +58,11 @@ inline static dtype m_rand(uint32_t max, int shift)
|
|
|
58
58
|
}
|
|
59
59
|
<% end %>
|
|
60
60
|
<%
|
|
61
|
+
elsif is_half
|
|
62
|
+
m_rand = "m_rand(max)"
|
|
63
|
+
shift_def = ""
|
|
64
|
+
shift_set = ""
|
|
65
|
+
rand_type = "float"
|
|
61
66
|
else
|
|
62
67
|
m_rand = "m_rand(max)"
|
|
63
68
|
shift_def = ""
|
|
@@ -102,7 +107,7 @@ static void
|
|
|
102
107
|
dtype x;
|
|
103
108
|
|
|
104
109
|
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
105
|
-
|
|
110
|
+
cumo_cuda_runtime_device_synchronize();
|
|
106
111
|
if (idx1) {
|
|
107
112
|
for (; i--;) {
|
|
108
113
|
x = m_add(<%=m_rand%>,low);
|
|
@@ -157,7 +162,13 @@ static VALUE
|
|
|
157
162
|
{
|
|
158
163
|
rand_opt_t g;
|
|
159
164
|
VALUE v1=Qnil, v2=Qnil;
|
|
165
|
+
<% if is_half %>
|
|
166
|
+
// The span is read in float: half cannot hold one wider than 65504, and
|
|
167
|
+
// subtracting the bounds in half would answer infinity for it.
|
|
168
|
+
float high;
|
|
169
|
+
<% else %>
|
|
160
170
|
dtype high;
|
|
171
|
+
<% end %>
|
|
161
172
|
cumo_ndfunc_arg_in_t ain[1] = {{CUMO_OVERWRITE,0}};
|
|
162
173
|
cumo_ndfunc_t ndf = {<%=c_iter%>, CUMO_FULL_LOOP, 1,0, ain,0};
|
|
163
174
|
|
|
@@ -173,17 +184,24 @@ static VALUE
|
|
|
173
184
|
if (v1==Qnil) {
|
|
174
185
|
<% if is_complex %>
|
|
175
186
|
g.max = high = c_new(1,1);
|
|
187
|
+
<% elsif is_half %>
|
|
188
|
+
g.max = high = 1.0f;
|
|
176
189
|
<% else %>
|
|
177
190
|
g.max = high = m_one;
|
|
178
191
|
<% end %>
|
|
179
192
|
} else {
|
|
180
|
-
g.max = high = m_num_to_data(v1)
|
|
193
|
+
g.max = high = <% if is_half %>(float)NUM2DBL(v1)<% else %>m_num_to_data(v1)<% end %>;
|
|
181
194
|
}
|
|
182
195
|
<% end %>
|
|
183
196
|
} else {
|
|
184
197
|
g.low = m_num_to_data(v1);
|
|
198
|
+
<% if is_half %>
|
|
199
|
+
high = (float)NUM2DBL(v2);
|
|
200
|
+
g.max = high - cumo_half2float(g.low);
|
|
201
|
+
<% else %>
|
|
185
202
|
high = m_num_to_data(v2);
|
|
186
203
|
g.max = m_sub(high,g.low);
|
|
204
|
+
<% end %>
|
|
187
205
|
}
|
|
188
206
|
<% if is_int && !is_object %>
|
|
189
207
|
if (high <= g.low) {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
if is_int && !is_object
|
|
3
3
|
rand_bit = (/Int64$/ =~ class_name) ? 64 : 32
|
|
4
4
|
rand_type = "uint#{rand_bit}_t"
|
|
5
|
+
elsif is_half
|
|
6
|
+
rand_type = "float"
|
|
5
7
|
else
|
|
6
8
|
rand_type = "dtype"
|
|
7
9
|
end
|
|
@@ -45,6 +47,17 @@ __device__ static dtype
|
|
|
45
47
|
CUMO_REAL(z) = cumo_rand_uniform(st) * CUMO_REAL(max) + CUMO_REAL(low);
|
|
46
48
|
CUMO_IMAG(z) = cumo_rand_uniform(st) * CUMO_IMAG(max) + CUMO_IMAG(low);
|
|
47
49
|
return z;
|
|
50
|
+
//<% elsif is_half %>
|
|
51
|
+
// Rounding the float into a half can land on the upper bound, which rand
|
|
52
|
+
// does not include, and the neighbour below it is the nearest value that
|
|
53
|
+
// does. A bound half cannot hold has no neighbour to step to.
|
|
54
|
+
float flow = cumo_half2float(low);
|
|
55
|
+
float high = flow + max;
|
|
56
|
+
dtype h = cumo_float2half(cumo_rand_uniform(st) * max + flow);
|
|
57
|
+
if (isfinite(high) && cumo_half2float(h) >= high) {
|
|
58
|
+
h = cumo_half_step_down(h);
|
|
59
|
+
}
|
|
60
|
+
return h;
|
|
48
61
|
//<% else %>
|
|
49
62
|
return (dtype)(cumo_rand_uniform(st) * max) + low;
|
|
50
63
|
//<% end %>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
typedef struct {
|
|
2
2
|
dtype mu;
|
|
3
|
-
rtype sigma;
|
|
3
|
+
<% if is_half %>float<% else %>rtype<% end %> sigma;
|
|
4
4
|
u_int64_t seed;
|
|
5
5
|
u_int64_t offset;
|
|
6
6
|
} randn_opt_t;
|
|
7
7
|
|
|
8
|
-
void <%="cumo_#{c_iter}_index_kernel_launch"%>(char *p1, size_t *idx1, uint64_t seed, uint64_t offset, dtype mu, rtype sigma, uint64_t n);
|
|
9
|
-
void <%="cumo_#{c_iter}_stride_kernel_launch"%>(char *p1, ssize_t s1, uint64_t seed, uint64_t offset, dtype mu, rtype sigma, uint64_t n);
|
|
8
|
+
void <%="cumo_#{c_iter}_index_kernel_launch"%>(char *p1, size_t *idx1, uint64_t seed, uint64_t offset, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma, uint64_t n);
|
|
9
|
+
void <%="cumo_#{c_iter}_stride_kernel_launch"%>(char *p1, ssize_t s1, uint64_t seed, uint64_t offset, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma, uint64_t n);
|
|
10
10
|
|
|
11
11
|
static void
|
|
12
12
|
<%=c_iter%>(cumo_na_loop_t *const lp)
|
|
@@ -16,7 +16,7 @@ static void
|
|
|
16
16
|
ssize_t s1;
|
|
17
17
|
size_t *idx1;
|
|
18
18
|
dtype mu;
|
|
19
|
-
rtype sigma;
|
|
19
|
+
<% if is_half %>float<% else %>rtype<% end %> sigma;
|
|
20
20
|
randn_opt_t *g;
|
|
21
21
|
|
|
22
22
|
CUMO_INIT_COUNTER(lp, i);
|
|
@@ -16,19 +16,21 @@
|
|
|
16
16
|
<% end %>
|
|
17
17
|
|
|
18
18
|
__device__ static dtype
|
|
19
|
-
<%="cumo_#{c_iter}_value"%>(curandStatePhilox4_32_10_t *st, dtype mu, rtype sigma)
|
|
19
|
+
<%="cumo_#{c_iter}_value"%>(curandStatePhilox4_32_10_t *st, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma)
|
|
20
20
|
{
|
|
21
21
|
//<% if is_complex %>
|
|
22
22
|
dtype z;
|
|
23
23
|
CUMO_REAL(z) = cumo_rand_normal(st) * sigma + CUMO_REAL(mu);
|
|
24
24
|
CUMO_IMAG(z) = cumo_rand_normal(st) * sigma + CUMO_IMAG(mu);
|
|
25
25
|
return z;
|
|
26
|
+
//<% elsif is_half %>
|
|
27
|
+
return cumo_float2half(cumo_rand_normal(st) * sigma + cumo_half2float(mu));
|
|
26
28
|
//<% else %>
|
|
27
29
|
return cumo_rand_normal(st) * sigma + mu;
|
|
28
30
|
//<% end %>
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
__global__ void <%="cumo_#{c_iter}_index_kernel"%>(char *p1, size_t *idx1, uint64_t seed, uint64_t offset, dtype mu, rtype sigma, uint64_t n)
|
|
33
|
+
__global__ void <%="cumo_#{c_iter}_index_kernel"%>(char *p1, size_t *idx1, uint64_t seed, uint64_t offset, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma, uint64_t n)
|
|
32
34
|
{
|
|
33
35
|
for (uint64_t i = blockIdx.x * blockDim.x + threadIdx.x; i < n; i += blockDim.x * gridDim.x) {
|
|
34
36
|
curandStatePhilox4_32_10_t st;
|
|
@@ -37,7 +39,7 @@ __global__ void <%="cumo_#{c_iter}_index_kernel"%>(char *p1, size_t *idx1, uint6
|
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
__global__ void <%="cumo_#{c_iter}_stride_kernel"%>(char *p1, ssize_t s1, uint64_t seed, uint64_t offset, dtype mu, rtype sigma, uint64_t n)
|
|
42
|
+
__global__ void <%="cumo_#{c_iter}_stride_kernel"%>(char *p1, ssize_t s1, uint64_t seed, uint64_t offset, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma, uint64_t n)
|
|
41
43
|
{
|
|
42
44
|
for (uint64_t i = blockIdx.x * blockDim.x + threadIdx.x; i < n; i += blockDim.x * gridDim.x) {
|
|
43
45
|
curandStatePhilox4_32_10_t st;
|
|
@@ -55,7 +57,7 @@ extern "C" {
|
|
|
55
57
|
#endif
|
|
56
58
|
#endif
|
|
57
59
|
|
|
58
|
-
void <%="cumo_#{c_iter}_index_kernel_launch"%>(char *p1, size_t *idx1, uint64_t seed, uint64_t offset, dtype mu, rtype sigma, uint64_t n)
|
|
60
|
+
void <%="cumo_#{c_iter}_index_kernel_launch"%>(char *p1, size_t *idx1, uint64_t seed, uint64_t offset, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma, uint64_t n)
|
|
59
61
|
{
|
|
60
62
|
size_t grid_dim = cumo_get_grid_dim(n);
|
|
61
63
|
size_t block_dim = cumo_get_block_dim(n);
|
|
@@ -63,7 +65,7 @@ void <%="cumo_#{c_iter}_index_kernel_launch"%>(char *p1, size_t *idx1, uint64_t
|
|
|
63
65
|
cumo_cuda_runtime_check_kernel_launch();
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
void <%="cumo_#{c_iter}_stride_kernel_launch"%>(char *p1, ssize_t s1, uint64_t seed, uint64_t offset, dtype mu, rtype sigma, uint64_t n)
|
|
68
|
+
void <%="cumo_#{c_iter}_stride_kernel_launch"%>(char *p1, ssize_t s1, uint64_t seed, uint64_t offset, dtype mu, <% if is_half %>float<% else %>rtype<% end %> sigma, uint64_t n)
|
|
67
69
|
{
|
|
68
70
|
size_t grid_dim = cumo_get_grid_dim(n);
|
|
69
71
|
size_t block_dim = cumo_get_block_dim(n);
|
|
@@ -5,102 +5,103 @@
|
|
|
5
5
|
} /* extern "C" { */
|
|
6
6
|
#endif
|
|
7
7
|
|
|
8
|
+
<% acc = is_half ? 'float' : dtype %>
|
|
9
|
+
<% to_acc = is_half ? 'cumo_half2float' : '' %>
|
|
10
|
+
<% from_acc = is_half ? 'cumo_float2half' : '' %>
|
|
11
|
+
<% acc_zero = is_half ? '0.0f' : 'm_zero' %>
|
|
12
|
+
|
|
13
|
+
|
|
8
14
|
// Reduce also combines two accumulators, so next has to be the accumulator type:
|
|
9
|
-
// the integer types widen to 64 bits and taking dtype there
|
|
10
|
-
// partial the shared-memory tree merges.
|
|
15
|
+
// the integer types widen to 64 bits and half to float, and taking dtype there
|
|
16
|
+
// truncates every partial the shared-memory tree merges.
|
|
11
17
|
struct cumo_<%=type_name%>_sum_impl {
|
|
12
|
-
__device__ <%=
|
|
13
|
-
__device__ <%=
|
|
14
|
-
__device__ void Reduce(<%=
|
|
15
|
-
__device__ <%=dtype%> MapOut(<%=
|
|
18
|
+
__device__ <%=acc%> Identity(int64_t /*index*/) { return <%=acc_zero%>; }
|
|
19
|
+
__device__ <%=acc%> MapIn(dtype in, int64_t /*index*/) { return <%=to_acc%>(in); }
|
|
20
|
+
__device__ void Reduce(<%=acc%> next, <%=acc%>& accum) { accum = accum + next; }
|
|
21
|
+
__device__ <%=dtype%> MapOut(<%=acc%> accum) { return <%=from_acc%>(accum); }
|
|
16
22
|
};
|
|
17
23
|
|
|
18
24
|
struct cumo_<%=type_name%>_prod_impl {
|
|
19
25
|
__device__ <%=dtype%> Identity(int64_t /*index*/) { return m_one; }
|
|
20
26
|
__device__ <%=dtype%> MapIn(dtype in, int64_t /*index*/) { return in; }
|
|
21
|
-
__device__ void Reduce(<%=dtype%> next, <%=dtype%>& accum) { accum
|
|
27
|
+
__device__ void Reduce(<%=dtype%> next, <%=dtype%>& accum) { accum = m_mul(accum, next); }
|
|
22
28
|
__device__ <%=dtype%> MapOut(<%=dtype%> accum) { return accum; }
|
|
23
29
|
};
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
// One set of rules answers for both components, and min, max, minmax and ptp
|
|
32
|
+
// all name a whole set rather than a rule each. A pair that mixes two sets --
|
|
33
|
+
// the nan-aware min beside the default max -- is then not expressible, which
|
|
34
|
+
// is the shape #372 had: #219 changed the identity in min and max and left the
|
|
35
|
+
// copies inside the fused pair behind.
|
|
36
|
+
struct cumo_<%=type_name%>_extremum_rules {
|
|
37
|
+
struct Min {
|
|
26
38
|
<% if is_float %>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
__device__ void Reduce(dtype next, dtype& accum) { if (next < accum || !not_nan(accum)) { accum = next; } }
|
|
39
|
+
// A NaN loses the comparison, so it is skipped unless the accumulator
|
|
40
|
+
// is still the identity: the reduction then answers NaN only when every
|
|
41
|
+
// element was NaN, and equal elements keep the earlier one as numo does.
|
|
42
|
+
__device__ static dtype Identity() { return (dtype)nan(""); }
|
|
43
|
+
__device__ static void Reduce(dtype next, dtype& accum) { if (m_lt(next, accum) || !not_nan(accum)) { accum = next; } }
|
|
33
44
|
<% else %>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
__device__ void Reduce(dtype next, dtype& accum) { accum = next < accum ? next : accum; }
|
|
45
|
+
__device__ static dtype Identity() { return DATA_MAX; }
|
|
46
|
+
__device__ static void Reduce(dtype next, dtype& accum) { accum = m_lt(next, accum) ? next : accum; }
|
|
37
47
|
<% end %>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
struct cumo_<%=type_name%>_max_impl {
|
|
48
|
+
};
|
|
49
|
+
struct Max {
|
|
42
50
|
<% if is_float %>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
__device__ void Reduce(dtype next, dtype& accum) { if (accum < next || !not_nan(accum)) { accum = next; } }
|
|
51
|
+
__device__ static dtype Identity() { return (dtype)nan(""); }
|
|
52
|
+
__device__ static void Reduce(dtype next, dtype& accum) { if (m_lt(accum, next) || !not_nan(accum)) { accum = next; } }
|
|
46
53
|
<% else %>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
__device__ void Reduce(dtype next, dtype& accum) { accum = next < accum ? accum : next; }
|
|
54
|
+
__device__ static dtype Identity() { return DATA_MIN; }
|
|
55
|
+
__device__ static void Reduce(dtype next, dtype& accum) { accum = m_lt(next, accum) ? accum : next; }
|
|
50
56
|
<% end %>
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
template <typename Rule>
|
|
61
|
+
struct cumo_<%=type_name%>_extremum_of {
|
|
62
|
+
__device__ dtype Identity(int64_t /*index*/) { return Rule::Identity(); }
|
|
63
|
+
__device__ dtype MapIn(dtype in, int64_t /*index*/) { return in; }
|
|
64
|
+
__device__ void Reduce(dtype next, dtype& accum) { Rule::Reduce(next, accum); }
|
|
51
65
|
__device__ dtype MapOut(dtype accum) { return accum; }
|
|
52
66
|
};
|
|
53
67
|
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
struct cumo_<%=type_name%>
|
|
68
|
+
// What minmax and ptp accumulate, and how it goes in and out. No Identity and
|
|
69
|
+
// no Reduce: those come from the rules, so a form that names none does not
|
|
70
|
+
// compile.
|
|
71
|
+
struct cumo_<%=type_name%>_minmax_pair {
|
|
58
72
|
struct MinAndMax {
|
|
59
73
|
dtype min;
|
|
60
74
|
dtype max;
|
|
61
75
|
};
|
|
62
|
-
<% if is_float %>
|
|
63
|
-
__device__ MinAndMax Identity(int64_t /*index*/) { return {(dtype)nan(""), (dtype)nan("")}; }
|
|
64
|
-
__device__ MinAndMax MapIn(dtype in, int64_t /*index*/) { return {in, in}; }
|
|
65
|
-
__device__ void Reduce(MinAndMax next, MinAndMax& accum) {
|
|
66
|
-
if (next.min < accum.min || !not_nan(accum.min)) { accum.min = next.min; }
|
|
67
|
-
if (accum.max < next.max || !not_nan(accum.max)) { accum.max = next.max; }
|
|
68
|
-
}
|
|
69
|
-
<% else %>
|
|
70
|
-
__device__ MinAndMax Identity(int64_t /*index*/) { return {DATA_MAX, DATA_MIN}; }
|
|
71
76
|
__device__ MinAndMax MapIn(dtype in, int64_t /*index*/) { return {in, in}; }
|
|
72
|
-
__device__ void Reduce(MinAndMax next, MinAndMax& accum) {
|
|
73
|
-
accum.min = next.min < accum.min ? next.min : accum.min;
|
|
74
|
-
accum.max = next.max < accum.max ? accum.max : next.max;
|
|
75
|
-
}
|
|
76
|
-
<% end %>
|
|
77
77
|
__device__ void MapOut(MinAndMax accum, dtype* out_min, dtype* out_max) {
|
|
78
78
|
*out_min = accum.min;
|
|
79
79
|
*out_max = accum.max;
|
|
80
80
|
}
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
};
|
|
88
|
-
__device__ MinAndMax Identity(int64_t /*index*/) { return {DATA_MAX, DATA_MIN}; }
|
|
89
|
-
__device__ MinAndMax MapIn(dtype in, int64_t /*index*/) { return {in, in}; }
|
|
83
|
+
// min and max fused, so that minmax reads the input once.
|
|
84
|
+
template <typename Rules>
|
|
85
|
+
struct cumo_<%=type_name%>_minmax_of : cumo_<%=type_name%>_minmax_pair {
|
|
86
|
+
__device__ MinAndMax Identity(int64_t /*index*/) { return {Rules::Min::Identity(), Rules::Max::Identity()}; }
|
|
90
87
|
__device__ void Reduce(MinAndMax next, MinAndMax& accum) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
__device__ dtype MapOut(MinAndMax accum) {
|
|
95
|
-
<% if is_float %>
|
|
96
|
-
// A NaN loses both comparisons above, so every element being NaN leaves
|
|
97
|
-
// the identity untouched. An empty reduction raises before it gets here.
|
|
98
|
-
if (accum.max < accum.min) { return (dtype)nan(""); }
|
|
99
|
-
<% end %>
|
|
100
|
-
return m_sub(accum.max, accum.min);
|
|
88
|
+
Rules::Min::Reduce(next.min, accum.min);
|
|
89
|
+
Rules::Max::Reduce(next.max, accum.max);
|
|
101
90
|
}
|
|
102
91
|
};
|
|
103
92
|
|
|
93
|
+
// ptp is its minmax with the pair subtracted. The one-argument MapOut hides
|
|
94
|
+
// the two-output one it inherits.
|
|
95
|
+
template <typename Rules>
|
|
96
|
+
struct cumo_<%=type_name%>_ptp_of : cumo_<%=type_name%>_minmax_of<Rules> {
|
|
97
|
+
__device__ dtype MapOut(cumo_<%=type_name%>_minmax_pair::MinAndMax accum) { return m_sub(accum.max, accum.min); }
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
using cumo_<%=type_name%>_min_impl = cumo_<%=type_name%>_extremum_of<cumo_<%=type_name%>_extremum_rules::Min>;
|
|
101
|
+
using cumo_<%=type_name%>_max_impl = cumo_<%=type_name%>_extremum_of<cumo_<%=type_name%>_extremum_rules::Max>;
|
|
102
|
+
using cumo_<%=type_name%>_minmax_impl = cumo_<%=type_name%>_minmax_of<cumo_<%=type_name%>_extremum_rules>;
|
|
103
|
+
using cumo_<%=type_name%>_ptp_impl = cumo_<%=type_name%>_ptp_of<cumo_<%=type_name%>_extremum_rules>;
|
|
104
|
+
|
|
104
105
|
<% unless is_float %>
|
|
105
106
|
// mean, var, stddev and rms answer in double for the integer types, so they
|
|
106
107
|
// accumulate in double too rather than in dtype.
|
|
@@ -155,11 +156,15 @@ struct cumo_<%=type_name%>_rms_impl {
|
|
|
155
156
|
// NaN, so it maps to the identity and the tree never sees it. min and max go
|
|
156
157
|
// the other way: numo answers NaN as soon as one element is NaN, and a NaN
|
|
157
158
|
// absorbs in Reduce because it loses every comparison.
|
|
159
|
+
//
|
|
160
|
+
// min and max take an infinity for their identity rather than the largest
|
|
161
|
+
// finite value, so that an element which is itself an infinity still wins.
|
|
162
|
+
// numo seeds from the first element and never faces the question.
|
|
158
163
|
struct cumo_<%=type_name%>_sum_nan_impl {
|
|
159
|
-
__device__
|
|
160
|
-
__device__
|
|
161
|
-
__device__ void Reduce(
|
|
162
|
-
__device__ dtype MapOut(
|
|
164
|
+
__device__ <%=acc%> Identity(int64_t /*index*/) { return <%=acc_zero%>; }
|
|
165
|
+
__device__ <%=acc%> MapIn(dtype in, int64_t /*index*/) { return not_nan(in) ? <%=to_acc%>(in) : <%=acc_zero%>; }
|
|
166
|
+
__device__ void Reduce(<%=acc%> next, <%=acc%>& accum) { accum = next + accum; }
|
|
167
|
+
__device__ dtype MapOut(<%=acc%> accum) { return <%=from_acc%>(accum); }
|
|
163
168
|
};
|
|
164
169
|
|
|
165
170
|
struct cumo_<%=type_name%>_prod_nan_impl {
|
|
@@ -169,40 +174,21 @@ struct cumo_<%=type_name%>_prod_nan_impl {
|
|
|
169
174
|
__device__ dtype MapOut(dtype accum) { return accum; }
|
|
170
175
|
};
|
|
171
176
|
|
|
172
|
-
struct cumo_<%=type_name%>
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
__device__ dtype Identity(int64_t /*index*/) { return DATA_MIN; }
|
|
181
|
-
__device__ dtype MapIn(dtype in, int64_t /*index*/) { return in; }
|
|
182
|
-
__device__ void Reduce(dtype next, dtype& accum) { if (!not_nan(next) || accum < next) { accum = next; } }
|
|
183
|
-
__device__ dtype MapOut(dtype accum) { return accum; }
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
struct cumo_<%=type_name%>_minmax_nan_impl {
|
|
187
|
-
struct MinAndMax {
|
|
188
|
-
dtype min;
|
|
189
|
-
dtype max;
|
|
177
|
+
struct cumo_<%=type_name%>_extremum_nan_rules {
|
|
178
|
+
struct Min {
|
|
179
|
+
__device__ static dtype Identity() { return (dtype)INFINITY; }
|
|
180
|
+
__device__ static void Reduce(dtype next, dtype& accum) { if (!not_nan(next) || m_lt(next, accum)) { accum = next; } }
|
|
181
|
+
};
|
|
182
|
+
struct Max {
|
|
183
|
+
__device__ static dtype Identity() { return (dtype)(-INFINITY); }
|
|
184
|
+
__device__ static void Reduce(dtype next, dtype& accum) { if (!not_nan(next) || m_lt(accum, next)) { accum = next; } }
|
|
190
185
|
};
|
|
191
|
-
__device__ MinAndMax Identity(int64_t /*index*/) { return {DATA_MAX, DATA_MIN}; }
|
|
192
|
-
__device__ MinAndMax MapIn(dtype in, int64_t /*index*/) { return {in, in}; }
|
|
193
|
-
__device__ void Reduce(MinAndMax next, MinAndMax& accum) {
|
|
194
|
-
if (!not_nan(next.min) || next.min < accum.min) { accum.min = next.min; }
|
|
195
|
-
if (!not_nan(next.max) || accum.max < next.max) { accum.max = next.max; }
|
|
196
|
-
}
|
|
197
|
-
__device__ void MapOut(MinAndMax accum, dtype* out_min, dtype* out_max) {
|
|
198
|
-
*out_min = accum.min;
|
|
199
|
-
*out_max = accum.max;
|
|
200
|
-
}
|
|
201
186
|
};
|
|
202
187
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
188
|
+
using cumo_<%=type_name%>_min_nan_impl = cumo_<%=type_name%>_extremum_of<cumo_<%=type_name%>_extremum_nan_rules::Min>;
|
|
189
|
+
using cumo_<%=type_name%>_max_nan_impl = cumo_<%=type_name%>_extremum_of<cumo_<%=type_name%>_extremum_nan_rules::Max>;
|
|
190
|
+
using cumo_<%=type_name%>_minmax_nan_impl = cumo_<%=type_name%>_minmax_of<cumo_<%=type_name%>_extremum_nan_rules>;
|
|
191
|
+
using cumo_<%=type_name%>_ptp_nan_impl = cumo_<%=type_name%>_ptp_of<cumo_<%=type_name%>_extremum_nan_rules>;
|
|
206
192
|
<% end %>
|
|
207
193
|
|
|
208
194
|
#if defined(__cplusplus)
|
|
@@ -42,7 +42,7 @@ static void
|
|
|
42
42
|
CUMO_INIT_COUNTER(lp, n);
|
|
43
43
|
CUMO_INIT_PTR(lp, 0, ptr, step);
|
|
44
44
|
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
45
|
-
|
|
45
|
+
cumo_cuda_runtime_device_synchronize();
|
|
46
46
|
<%=type_name%>_qsort<%=j%>(ptr, n, step);
|
|
47
47
|
}
|
|
48
48
|
<% end %>
|
|
@@ -50,6 +50,12 @@ static void
|
|
|
50
50
|
|
|
51
51
|
ptr = (char**)(lp->opt_ptr);
|
|
52
52
|
|
|
53
|
+
// The row is managed memory that ndloop may have just filled with a copy
|
|
54
|
+
// kernel, and everything below reads it on the host. Per row rather than
|
|
55
|
+
// once for the call, because that copy happens per row.
|
|
56
|
+
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
57
|
+
cumo_cuda_runtime_device_synchronize();
|
|
58
|
+
|
|
53
59
|
//printf("(ptr=%lx, d_ptr=%lx,d_step=%ld, i_ptr=%lx,i_step=%ld, o_ptr=%lx,o_step=%ld)\n",(size_t)ptr,(size_t)d_ptr,(ssize_t)d_step,(size_t)i_ptr,(ssize_t)i_step,(size_t)o_ptr,(ssize_t)o_step);
|
|
54
60
|
|
|
55
61
|
if (n==1) {
|
|
@@ -153,9 +159,6 @@ static VALUE
|
|
|
153
159
|
size = na->size*sizeof(void*); // max capa
|
|
154
160
|
buf = rb_alloc_tmp_buffer(&tmp, size);
|
|
155
161
|
|
|
156
|
-
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
157
|
-
cudaDeviceSynchronize();
|
|
158
|
-
|
|
159
162
|
res = cumo_na_ndloop3(&ndf, buf, 3, self, idx, reduce);
|
|
160
163
|
rb_free_tmp_buffer(&tmp);
|
|
161
164
|
return res;
|
|
@@ -24,29 +24,29 @@ static void
|
|
|
24
24
|
v1 = lp->args[1].value;
|
|
25
25
|
i = 0;
|
|
26
26
|
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
if (CumoIsNArray(v1)) {
|
|
28
|
+
// shape[0] is how many elements the sub-narray offers at this row,
|
|
29
|
+
// which is zero where it does not reach. The loop counter is the
|
|
30
|
+
// destination length, so copying more would read past the row's end.
|
|
31
|
+
i = lp->args[1].shape[0];
|
|
32
|
+
if (i > n) {
|
|
33
|
+
i = n;
|
|
34
|
+
}
|
|
35
|
+
if (i > 0) {
|
|
36
36
|
CUMO_NDL_CNT(lp) = i;
|
|
37
37
|
iter_<%=type_name%>_store_<%=type_name%>(lp);
|
|
38
38
|
CUMO_NDL_CNT(lp) = n;
|
|
39
|
-
//<% if c_iter.include? 'robject' %>
|
|
40
|
-
// The zero fill below walks from here. The kernel the other branch
|
|
41
|
-
// launches takes the offset of the first element left to fill as an
|
|
42
|
-
// argument instead, so advancing for it would count i twice.
|
|
43
|
-
if (idx1) {
|
|
44
|
-
idx1 += i;
|
|
45
|
-
} else {
|
|
46
|
-
p1 += s1 * i;
|
|
47
|
-
}
|
|
48
|
-
//<% end %>
|
|
49
39
|
}
|
|
40
|
+
//<% if c_iter.include? 'robject' %>
|
|
41
|
+
// The zero fill below walks from here. The kernel the other branch
|
|
42
|
+
// launches takes the offset of the first element left to fill as an
|
|
43
|
+
// argument instead, so advancing for it would count i twice.
|
|
44
|
+
if (idx1) {
|
|
45
|
+
idx1 += i;
|
|
46
|
+
} else {
|
|
47
|
+
p1 += s1 * i;
|
|
48
|
+
}
|
|
49
|
+
//<% end %>
|
|
50
50
|
goto loop_end;
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -55,8 +55,7 @@ static void
|
|
|
55
55
|
n1 = RARRAY_LEN(v1);
|
|
56
56
|
break;
|
|
57
57
|
case T_NIL:
|
|
58
|
-
|
|
59
|
-
break;
|
|
58
|
+
goto loop_end;
|
|
60
59
|
default:
|
|
61
60
|
n1 = 1;
|
|
62
61
|
}
|
|
@@ -64,7 +63,7 @@ static void
|
|
|
64
63
|
//<% if c_iter.include? 'robject' %>
|
|
65
64
|
{
|
|
66
65
|
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("store_<%=name%>", "<%=type_name%>");
|
|
67
|
-
|
|
66
|
+
cumo_cuda_runtime_device_synchronize();
|
|
68
67
|
|
|
69
68
|
if (idx1) {
|
|
70
69
|
for (i=i1=0; i1<n1 && i<n; i1++) {
|
|
@@ -23,7 +23,7 @@ static void
|
|
|
23
23
|
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
24
24
|
// The index arrays are filled by a kernel; wait for it before reading
|
|
25
25
|
// them from here.
|
|
26
|
-
|
|
26
|
+
cumo_cuda_runtime_device_synchronize();
|
|
27
27
|
if (idx2) {
|
|
28
28
|
if (idx1) {
|
|
29
29
|
for (; i--;) {
|
|
@@ -34,7 +34,7 @@ static void
|
|
|
34
34
|
// until that has finished. Cumo::RObject is the only dtype whose loop runs
|
|
35
35
|
// on the host and still sees the index; every other one hands it to a
|
|
36
36
|
// kernel of its own, which the stream already orders.
|
|
37
|
-
|
|
37
|
+
cumo_cuda_runtime_device_synchronize();
|
|
38
38
|
{
|
|
39
39
|
<%=dtype%> x;
|
|
40
40
|
dtype y;
|
|
@@ -40,10 +40,45 @@ void <%="cumo_#{c_iter}_stridx_kernel_launch"%>(cumo_na_iarray_stridx_t* a1, cum
|
|
|
40
40
|
cumo_cuda_runtime_check_kernel_launch();
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
__global__ void <%="cumo_#{c_iter}_transpose_kernel"%>(char *p1, char *p2, uint64_t rows, uint64_t cols)
|
|
44
|
+
{
|
|
45
|
+
CUMO_TRANSPOSE_TILE_DECL(dtype, tile);
|
|
46
|
+
|
|
47
|
+
CUMO_TRANSPOSE_TILE_LOOP(tile, rows, cols,
|
|
48
|
+
<%=macro%>(*(<%=dtype%>*)(p2 + cumo_tile_src * sizeof(<%=dtype%>))),
|
|
49
|
+
*(dtype*)(p1 + cumo_tile_dst * sizeof(dtype)) = cumo_tile_val;
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// True when the destination runs along its rows and the source along its
|
|
54
|
+
// columns, which is what a copy of a transposed view looks like. A side shorter
|
|
55
|
+
// than a tile leaves most of each warp idle, and the plain loop already reads or
|
|
56
|
+
// writes such a side in one go, so the tiles only pay off once both sides reach
|
|
57
|
+
// one.
|
|
58
|
+
static int
|
|
59
|
+
<%="cumo_#{c_iter}_is_transpose"%>(cumo_na_iarray_t* a1, cumo_na_iarray_t* a2, cumo_na_indexer_t* indexer)
|
|
60
|
+
{
|
|
61
|
+
return CUMO_TRANSPOSE_TILE_FITS(indexer) &&
|
|
62
|
+
a1->step[1] == (ssize_t)sizeof(dtype) &&
|
|
63
|
+
a1->step[0] == (ssize_t)(sizeof(dtype) * indexer->shape[1]) &&
|
|
64
|
+
a2->step[0] == (ssize_t)sizeof(<%=dtype%>) &&
|
|
65
|
+
a2->step[1] == (ssize_t)(sizeof(<%=dtype%>) * indexer->shape[0]);
|
|
66
|
+
}
|
|
67
|
+
|
|
43
68
|
void <%="cumo_#{c_iter}_kernel_launch"%>(cumo_na_iarray_t* a1, cumo_na_iarray_t* a2, cumo_na_indexer_t* indexer)
|
|
44
69
|
{
|
|
45
|
-
size_t grid_dim
|
|
46
|
-
|
|
70
|
+
size_t grid_dim, block_dim;
|
|
71
|
+
|
|
72
|
+
if (<%="cumo_#{c_iter}_is_transpose"%>(a1, a2, indexer)) {
|
|
73
|
+
CUMO_TRANSPOSE_LAUNCH(<%="cumo_#{c_iter}_transpose_kernel"%>,
|
|
74
|
+
indexer->shape[0], indexer->shape[1],
|
|
75
|
+
a1->ptr, a2->ptr);
|
|
76
|
+
cumo_cuda_runtime_check_kernel_launch();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
grid_dim = cumo_get_grid_dim(indexer->total_size);
|
|
81
|
+
block_dim = cumo_get_block_dim(indexer->total_size);
|
|
47
82
|
switch (indexer->ndim) {
|
|
48
83
|
<% (0..opt_indexer_ndim).each do |idim| %>
|
|
49
84
|
case <%=idim%>:
|
|
@@ -38,6 +38,6 @@ static VALUE
|
|
|
38
38
|
cumo_ndfunc_arg_out_t aout[1] = {{rb_cArray,0}}; // dummy?
|
|
39
39
|
cumo_ndfunc_t ndf = { <%=c_iter%>, CUMO_FULL_LOOP_NIP, 3, 1, ain, aout };
|
|
40
40
|
CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
41
|
-
|
|
41
|
+
cumo_cuda_runtime_device_synchronize();
|
|
42
42
|
return cumo_na_ndloop_cast_narray_to_rarray(&ndf, self, Qnil);
|
|
43
43
|
}
|