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,4 +1,8 @@
|
|
|
1
1
|
<%= load_erb('real_accum').result(binding) %>
|
|
2
|
+
<% acc = is_half ? 'float' : 'dtype' %>
|
|
3
|
+
<% to_acc = is_half ? 'cumo_half2float' : '' %>
|
|
4
|
+
<% from_acc = is_half ? 'cumo_float2half' : '' %>
|
|
5
|
+
|
|
2
6
|
|
|
3
7
|
#if defined(__cplusplus)
|
|
4
8
|
#if 0
|
|
@@ -14,47 +18,47 @@
|
|
|
14
18
|
// divide 0 by 0 and leave the accumulator NaN.
|
|
15
19
|
struct cumo_<%=type_name%>_moments_impl {
|
|
16
20
|
struct Moments {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
<%=acc%> n;
|
|
22
|
+
<%=acc%> mean;
|
|
23
|
+
<%=acc%> m2;
|
|
20
24
|
};
|
|
21
|
-
__device__ Moments Identity(int64_t /*index*/) { return {0,
|
|
22
|
-
__device__ Moments MapIn(dtype in, int64_t /*index*/) { return {1, in, 0}; }
|
|
25
|
+
__device__ Moments Identity(int64_t /*index*/) { return {0, 0, 0}; }
|
|
26
|
+
__device__ Moments MapIn(dtype in, int64_t /*index*/) { return {1, <%=to_acc%>(in), 0}; }
|
|
23
27
|
__device__ void Reduce(Moments next, Moments& accum) {
|
|
24
28
|
if (next.n == 0) { return; }
|
|
25
29
|
if (accum.n == 0) { accum = next; return; }
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
accum.mean =
|
|
30
|
+
<%=acc%> n = accum.n + next.n;
|
|
31
|
+
<%=acc%> delta = next.mean - accum.mean;
|
|
32
|
+
accum.mean = accum.mean + delta * (next.n / n);
|
|
29
33
|
accum.m2 += next.m2 + delta * delta * accum.n * next.n / n;
|
|
30
34
|
accum.n = n;
|
|
31
35
|
}
|
|
32
36
|
};
|
|
33
37
|
|
|
34
38
|
struct cumo_<%=type_name%>_var_impl : cumo_<%=type_name%>_moments_impl {
|
|
35
|
-
__device__ rtype MapOut(Moments accum) { return accum.m2 / (accum.n - 1); }
|
|
39
|
+
__device__ rtype MapOut(Moments accum) { return <%=from_acc%>(accum.m2 / (accum.n - 1)); }
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
struct cumo_<%=type_name%>_stddev_impl : cumo_<%=type_name%>_moments_impl {
|
|
39
|
-
__device__ rtype MapOut(Moments accum) { return
|
|
43
|
+
__device__ rtype MapOut(Moments accum) { return <%=from_acc%>(sqrt(accum.m2 / (accum.n - 1))); }
|
|
40
44
|
};
|
|
41
45
|
|
|
42
46
|
struct cumo_<%=type_name%>_mean_impl {
|
|
43
47
|
// The reduce axis is the same length for every output, so the divisor is a
|
|
44
48
|
// constant the launcher already knows rather than a count the tree carries.
|
|
45
|
-
|
|
46
|
-
__device__
|
|
47
|
-
__device__
|
|
48
|
-
__device__ void Reduce(
|
|
49
|
-
__device__ dtype MapOut(
|
|
49
|
+
<%=acc%> n;
|
|
50
|
+
__device__ <%=acc%> Identity(int64_t /*index*/) { return 0; }
|
|
51
|
+
__device__ <%=acc%> MapIn(dtype in, int64_t /*index*/) { return <%=to_acc%>(in); }
|
|
52
|
+
__device__ void Reduce(<%=acc%> next, <%=acc%>& accum) { accum = next + accum; }
|
|
53
|
+
__device__ dtype MapOut(<%=acc%> accum) { return <%=from_acc%>(accum / n); }
|
|
50
54
|
};
|
|
51
55
|
|
|
52
56
|
struct cumo_<%=type_name%>_rms_impl {
|
|
53
|
-
|
|
54
|
-
__device__
|
|
55
|
-
__device__
|
|
56
|
-
__device__ void Reduce(
|
|
57
|
-
__device__ rtype MapOut(
|
|
57
|
+
<%=acc%> n;
|
|
58
|
+
__device__ <%=acc%> Identity(int64_t /*index*/) { return 0; }
|
|
59
|
+
__device__ <%=acc%> MapIn(dtype in, int64_t /*index*/) { <%=acc%> x = <%=to_acc%>(in); return x * x; }
|
|
60
|
+
__device__ void Reduce(<%=acc%> next, <%=acc%>& accum) { accum += next; }
|
|
61
|
+
__device__ rtype MapOut(<%=acc%> accum) { return <%=from_acc%>(sqrt(accum / n)); }
|
|
58
62
|
};
|
|
59
63
|
|
|
60
64
|
// The nan-aware forms. A NaN maps to an accumulator that contributes nothing:
|
|
@@ -63,8 +67,8 @@ struct cumo_<%=type_name%>_rms_impl {
|
|
|
63
67
|
// of the reduce axis.
|
|
64
68
|
struct cumo_<%=type_name%>_moments_nan_impl : cumo_<%=type_name%>_moments_impl {
|
|
65
69
|
__device__ Moments MapIn(dtype in, int64_t /*index*/) {
|
|
66
|
-
if (!not_nan(in)) { return {0,
|
|
67
|
-
return {1, in, 0};
|
|
70
|
+
if (!not_nan(in)) { return {0, 0, 0}; }
|
|
71
|
+
return {1, <%=to_acc%>(in), 0};
|
|
68
72
|
}
|
|
69
73
|
};
|
|
70
74
|
|
|
@@ -72,45 +76,46 @@ struct cumo_<%=type_name%>_var_nan_impl : cumo_<%=type_name%>_moments_nan_impl {
|
|
|
72
76
|
// Every element being NaN leaves no count. numo divides by count-1 in
|
|
73
77
|
// unsigned arithmetic there, so it answers +0 rather than the -0 that
|
|
74
78
|
// dividing by -1 would give.
|
|
75
|
-
__device__ rtype MapOut(Moments accum) { return accum.n == 0 ? 0 : accum.m2 / (accum.n - 1); }
|
|
79
|
+
__device__ rtype MapOut(Moments accum) { return accum.n == 0 ? <%=from_acc%>(0) : <%=from_acc%>(accum.m2 / (accum.n - 1)); }
|
|
76
80
|
};
|
|
77
81
|
|
|
78
82
|
struct cumo_<%=type_name%>_stddev_nan_impl : cumo_<%=type_name%>_moments_nan_impl {
|
|
79
|
-
__device__ rtype MapOut(Moments accum) { return accum.n == 0 ? 0 :
|
|
83
|
+
__device__ rtype MapOut(Moments accum) { return accum.n == 0 ? <%=from_acc%>(0) : <%=from_acc%>(sqrt(accum.m2 / (accum.n - 1))); }
|
|
80
84
|
};
|
|
81
85
|
|
|
82
86
|
struct cumo_<%=type_name%>_mean_nan_impl {
|
|
83
87
|
struct SumAndCount {
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
<%=acc%> sum;
|
|
89
|
+
<%=acc%> n;
|
|
86
90
|
};
|
|
87
|
-
__device__ SumAndCount Identity(int64_t /*index*/) { return {
|
|
91
|
+
__device__ SumAndCount Identity(int64_t /*index*/) { return {0, 0}; }
|
|
88
92
|
__device__ SumAndCount MapIn(dtype in, int64_t /*index*/) {
|
|
89
|
-
if (!not_nan(in)) { return {
|
|
90
|
-
return {in, 1};
|
|
93
|
+
if (!not_nan(in)) { return {0, 0}; }
|
|
94
|
+
return {<%=to_acc%>(in), 1};
|
|
91
95
|
}
|
|
92
96
|
__device__ void Reduce(SumAndCount next, SumAndCount& accum) {
|
|
93
|
-
accum.sum =
|
|
97
|
+
accum.sum = next.sum + accum.sum;
|
|
94
98
|
accum.n += next.n;
|
|
95
99
|
}
|
|
96
|
-
__device__ dtype MapOut(SumAndCount accum) { return
|
|
100
|
+
__device__ dtype MapOut(SumAndCount accum) { return <%=from_acc%>(accum.sum / accum.n); }
|
|
97
101
|
};
|
|
98
102
|
|
|
99
103
|
struct cumo_<%=type_name%>_rms_nan_impl {
|
|
100
104
|
struct SumAndCount {
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
<%=acc%> sum;
|
|
106
|
+
<%=acc%> n;
|
|
103
107
|
};
|
|
104
108
|
__device__ SumAndCount Identity(int64_t /*index*/) { return {0, 0}; }
|
|
105
109
|
__device__ SumAndCount MapIn(dtype in, int64_t /*index*/) {
|
|
106
110
|
if (!not_nan(in)) { return {0, 0}; }
|
|
107
|
-
|
|
111
|
+
<%=acc%> x = <%=to_acc%>(in);
|
|
112
|
+
return {x * x, 1};
|
|
108
113
|
}
|
|
109
114
|
__device__ void Reduce(SumAndCount next, SumAndCount& accum) {
|
|
110
115
|
accum.sum += next.sum;
|
|
111
116
|
accum.n += next.n;
|
|
112
117
|
}
|
|
113
|
-
__device__ rtype MapOut(SumAndCount accum) { return
|
|
118
|
+
__device__ rtype MapOut(SumAndCount accum) { return <%=from_acc%>(sqrt(accum.sum / accum.n)); }
|
|
114
119
|
};
|
|
115
120
|
|
|
116
121
|
<% if is_double_precision %>
|
|
@@ -154,7 +159,7 @@ extern "C" {
|
|
|
154
159
|
|
|
155
160
|
void cumo_<%=type_name%>_mean_kernel_launch(cumo_na_reduction_arg_t* arg)
|
|
156
161
|
{
|
|
157
|
-
|
|
162
|
+
<%=acc%> n = (<%=acc%>)(arg->in_indexer.total_size / arg->out_indexer.total_size);
|
|
158
163
|
cumo_reduce_split<dtype, dtype, cumo_<%=type_name%>_mean_impl>(*arg, cumo_<%=type_name%>_mean_impl{n});
|
|
159
164
|
}
|
|
160
165
|
|
|
@@ -170,7 +175,7 @@ void cumo_<%=type_name%>_stddev_kernel_launch(cumo_na_reduction_arg_t* arg)
|
|
|
170
175
|
|
|
171
176
|
void cumo_<%=type_name%>_rms_kernel_launch(cumo_na_reduction_arg_t* arg)
|
|
172
177
|
{
|
|
173
|
-
|
|
178
|
+
<%=acc%> n = (<%=acc%>)(arg->in_indexer.total_size / arg->out_indexer.total_size);
|
|
174
179
|
cumo_reduce_split<dtype, rtype, cumo_<%=type_name%>_rms_impl>(*arg, cumo_<%=type_name%>_rms_impl{n});
|
|
175
180
|
}
|
|
176
181
|
|
|
@@ -65,6 +65,6 @@ static VALUE
|
|
|
65
65
|
cumo_ndfunc_t ndf = { <%=c_iter%>, CUMO_FULL_LOOP_NIP, 2, 1, ain, aout };
|
|
66
66
|
|
|
67
67
|
rb_scan_args(argc, argv, "01", &fmt);
|
|
68
|
-
|
|
68
|
+
cumo_cuda_runtime_device_synchronize();
|
|
69
69
|
return cumo_na_ndloop(&ndf, 2, self, fmt);
|
|
70
70
|
}
|
|
@@ -44,6 +44,6 @@ static VALUE
|
|
|
44
44
|
cumo_ndfunc_t ndf = { <%=c_iter%>, CUMO_FULL_LOOP_NIP, 3, 1, ain, aout };
|
|
45
45
|
|
|
46
46
|
rb_scan_args(argc, argv, "01", &fmt);
|
|
47
|
-
|
|
47
|
+
cumo_cuda_runtime_device_synchronize();
|
|
48
48
|
return cumo_na_ndloop_cast_narray_to_rarray(&ndf, self, fmt);
|
|
49
49
|
}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
end
|
|
13
13
|
cutype =
|
|
14
14
|
case type_name
|
|
15
|
+
when 'hfloat'
|
|
16
|
+
'cumo_half'
|
|
15
17
|
when 'sfloat'
|
|
16
18
|
'float'
|
|
17
19
|
when 'dfloat'
|
|
@@ -21,6 +23,12 @@
|
|
|
21
23
|
when 'dcomplex'
|
|
22
24
|
'cuDoubleComplex'
|
|
23
25
|
end
|
|
26
|
+
# cublasGemmStridedBatchedEx multiplies in half and accumulates in float, and
|
|
27
|
+
# takes its scalars in the accumulator's type.
|
|
28
|
+
scalar_t = is_half ? 'float' : 'dtype'
|
|
29
|
+
num_to_scalar = is_half ? '(float)NUM2DBL' : 'm_num_to_data'
|
|
30
|
+
scalar_one = is_half ? '1.0f' : 'm_one'
|
|
31
|
+
scalar_zero = is_half ? '0.0f' : 'm_zero'
|
|
24
32
|
%>
|
|
25
33
|
|
|
26
34
|
#define ROW_SIZE(na) ((na)->shape[(na)->ndim-2])
|
|
@@ -102,18 +110,31 @@
|
|
|
102
110
|
} \
|
|
103
111
|
}
|
|
104
112
|
|
|
113
|
+
#include <limits.h>
|
|
114
|
+
|
|
105
115
|
typedef struct {
|
|
106
|
-
|
|
116
|
+
<%=scalar_t%> alpha, beta;
|
|
107
117
|
int m, n, k;
|
|
108
118
|
} gemm_args_t;
|
|
109
119
|
|
|
110
120
|
typedef struct {
|
|
111
121
|
int ld;
|
|
112
|
-
int stride; // in element count
|
|
122
|
+
long long int stride; // in element count
|
|
113
123
|
cublasOperation_t trans;
|
|
114
124
|
VALUE a;
|
|
115
125
|
} gemm_layout_t;
|
|
116
126
|
|
|
127
|
+
// cuBLAS takes these as int, so a shape that does not fit has to be refused
|
|
128
|
+
// rather than wrapped into a smaller or negative one.
|
|
129
|
+
static int
|
|
130
|
+
gemm_int(size_t v, const char *name)
|
|
131
|
+
{
|
|
132
|
+
if (v > INT_MAX) {
|
|
133
|
+
rb_raise(rb_eRangeError, "%s=%"SZF"u is too large for cuBLAS", name, v);
|
|
134
|
+
}
|
|
135
|
+
return (int)v;
|
|
136
|
+
}
|
|
137
|
+
|
|
117
138
|
static bool
|
|
118
139
|
is_f_contiguous(VALUE a)
|
|
119
140
|
{
|
|
@@ -192,7 +213,7 @@ static int
|
|
|
192
213
|
gemm_batch_count(cumo_narray_t *na)
|
|
193
214
|
{
|
|
194
215
|
size_t matrix_size = ROW_SIZE(na) * COL_SIZE(na);
|
|
195
|
-
return matrix_size == 0 ? 0 : (
|
|
216
|
+
return matrix_size == 0 ? 0 : gemm_int(CUMO_NA_SIZE(na) / matrix_size, "batch count");
|
|
196
217
|
}
|
|
197
218
|
|
|
198
219
|
static gemm_layout_t
|
|
@@ -210,27 +231,27 @@ make_gemm_layout(VALUE a)
|
|
|
210
231
|
}
|
|
211
232
|
|
|
212
233
|
if ((CUMO_NA_NDIM(na) == 2 && is_f_contiguous(a)) || is_batched_f_contiguous(a)) {
|
|
213
|
-
layout.ld = ROW_SIZE(na);
|
|
234
|
+
layout.ld = (int)ROW_SIZE(na);
|
|
214
235
|
layout.trans = CUBLAS_OP_T;
|
|
215
236
|
layout.a = a;
|
|
216
237
|
} else {
|
|
217
|
-
layout.ld = COL_SIZE(na);
|
|
238
|
+
layout.ld = (int)COL_SIZE(na);
|
|
218
239
|
layout.trans = CUBLAS_OP_N; // transposed
|
|
219
240
|
// force c-contiguous
|
|
220
241
|
layout.a = is_c_contiguous(a) ? a : rb_funcall(a, rb_intern("dup"), 0);
|
|
221
242
|
}
|
|
222
243
|
// cuBLAS walks the operand by this stride once per batch, so an operand that
|
|
223
244
|
// holds a single matrix has to be re-read rather than advanced past its end.
|
|
224
|
-
layout.stride = gemm_batch_count(na) == 1 ? 0 : ROW_SIZE(na) * COL_SIZE(na);
|
|
245
|
+
layout.stride = gemm_batch_count(na) == 1 ? 0 : (long long int)(ROW_SIZE(na) * COL_SIZE(na));
|
|
225
246
|
return layout;
|
|
226
247
|
}
|
|
227
248
|
|
|
228
249
|
extern int cumo_na_debug_flag; // narray.c
|
|
229
250
|
|
|
230
251
|
static void
|
|
231
|
-
print_gemm_args(gemm_args_t* g, gemm_layout_t* a_layout, gemm_layout_t* b_layout, int stridec, int batch_count)
|
|
252
|
+
print_gemm_args(gemm_args_t* g, gemm_layout_t* a_layout, gemm_layout_t* b_layout, long long int stridec, int batch_count)
|
|
232
253
|
{
|
|
233
|
-
printf("transb=%d transa=%d, n=%d, m=%d, k=%d, ldb=%d, lda=%d, ldc=n=%d, strideb=%
|
|
254
|
+
printf("transb=%d transa=%d, n=%d, m=%d, k=%d, ldb=%d, lda=%d, ldc=n=%d, strideb=%lld, stridea=%lld stridec=%lld batch_count=%d\n",
|
|
234
255
|
(int)b_layout->trans,
|
|
235
256
|
(int)a_layout->trans,
|
|
236
257
|
(int)g->n,
|
|
@@ -239,9 +260,9 @@ print_gemm_args(gemm_args_t* g, gemm_layout_t* a_layout, gemm_layout_t* b_layout
|
|
|
239
260
|
(int)b_layout->ld,
|
|
240
261
|
(int)a_layout->ld,
|
|
241
262
|
(int)g->n,
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
263
|
+
b_layout->stride,
|
|
264
|
+
a_layout->stride,
|
|
265
|
+
stridec,
|
|
245
266
|
(int)batch_count);
|
|
246
267
|
}
|
|
247
268
|
|
|
@@ -252,7 +273,8 @@ static void
|
|
|
252
273
|
cublasHandle_t handle = 0;
|
|
253
274
|
cublasStatus_t status = 0;
|
|
254
275
|
cumo_narray_t* nc;
|
|
255
|
-
|
|
276
|
+
size_t matrix_size;
|
|
277
|
+
long long int stridec = 0;
|
|
256
278
|
int batch_count = 0;
|
|
257
279
|
|
|
258
280
|
// Note that cuBLAS uses the column major matrix representation.
|
|
@@ -270,11 +292,38 @@ static void
|
|
|
270
292
|
b_layout = make_gemm_layout(b);
|
|
271
293
|
|
|
272
294
|
CumoGetNArray(c, nc);
|
|
273
|
-
|
|
274
|
-
|
|
295
|
+
matrix_size = ROW_SIZE(nc) * COL_SIZE(nc);
|
|
296
|
+
stridec = (long long int)matrix_size;
|
|
297
|
+
batch_count = gemm_int(CUMO_NA_SIZE(nc) / matrix_size, "batch count");
|
|
275
298
|
|
|
276
299
|
if (cumo_na_debug_flag) print_gemm_args(g, &a_layout, &b_layout, stridec, batch_count);
|
|
277
300
|
handle = cumo_cuda_cublas_handle();
|
|
301
|
+
<% if is_half %>
|
|
302
|
+
status = cublasGemmStridedBatchedEx(
|
|
303
|
+
handle,
|
|
304
|
+
b_layout.trans,
|
|
305
|
+
a_layout.trans,
|
|
306
|
+
g->n,
|
|
307
|
+
g->m,
|
|
308
|
+
g->k,
|
|
309
|
+
&g->alpha,
|
|
310
|
+
(const void*)(cumo_na_get_pointer_for_read(b_layout.a) + cumo_na_get_offset(b_layout.a)),
|
|
311
|
+
CUDA_R_16F,
|
|
312
|
+
b_layout.ld,
|
|
313
|
+
b_layout.stride,
|
|
314
|
+
(const void*)(cumo_na_get_pointer_for_read(a_layout.a) + cumo_na_get_offset(a_layout.a)),
|
|
315
|
+
CUDA_R_16F,
|
|
316
|
+
a_layout.ld,
|
|
317
|
+
a_layout.stride,
|
|
318
|
+
&g->beta,
|
|
319
|
+
(void*)(cumo_na_get_pointer_for_write(c) + cumo_na_get_offset(c)),
|
|
320
|
+
CUDA_R_16F,
|
|
321
|
+
g->n,
|
|
322
|
+
stridec,
|
|
323
|
+
batch_count,
|
|
324
|
+
CUBLAS_COMPUTE_32F,
|
|
325
|
+
CUBLAS_GEMM_DEFAULT);
|
|
326
|
+
<% else %>
|
|
278
327
|
status = cublas<%=func_prefix%>gemmStridedBatched(
|
|
279
328
|
handle,
|
|
280
329
|
b_layout.trans,
|
|
@@ -294,6 +343,7 @@ static void
|
|
|
294
343
|
g->n,
|
|
295
344
|
stridec,
|
|
296
345
|
batch_count);
|
|
346
|
+
<% end %>
|
|
297
347
|
cumo_cuda_cublas_check_status(status);
|
|
298
348
|
}
|
|
299
349
|
|
|
@@ -350,9 +400,9 @@ static VALUE
|
|
|
350
400
|
rb_scan_args(argc, argv, "11:", &b, &c, &kw_hash);
|
|
351
401
|
rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
|
|
352
402
|
alpha = cumo_cuda_cublas_option_value(opts[0],Qnil);
|
|
353
|
-
g.alpha = RTEST(alpha) ?
|
|
403
|
+
g.alpha = RTEST(alpha) ? <%=num_to_scalar%>(alpha) : <%=scalar_one%>;
|
|
354
404
|
beta = cumo_cuda_cublas_option_value(opts[1],Qnil);
|
|
355
|
-
g.beta = RTEST(beta) ?
|
|
405
|
+
g.beta = RTEST(beta) ? <%=num_to_scalar%>(beta) : <%=scalar_zero%>;
|
|
356
406
|
|
|
357
407
|
// b is handed to cuBLAS as a raw <%=cutype%>*, so another dtype would be
|
|
358
408
|
// reinterpreted, and a narrower one read past its end.
|
|
@@ -368,13 +418,13 @@ static VALUE
|
|
|
368
418
|
CHECK_NON_EMPTY(nb);
|
|
369
419
|
|
|
370
420
|
if (ROW_SIZE(nb) != COL_SIZE(na)) {
|
|
371
|
-
rb_raise(cumo_na_eShapeError,"ROW_SIZE(b)=%
|
|
372
|
-
|
|
421
|
+
rb_raise(cumo_na_eShapeError,"ROW_SIZE(b)=%"SZF"u must equal to COL_SIZE(a)=%"SZF"u",
|
|
422
|
+
ROW_SIZE(nb), COL_SIZE(na));
|
|
373
423
|
}
|
|
374
424
|
|
|
375
|
-
g.m = ROW_SIZE(na);
|
|
376
|
-
g.k = COL_SIZE(na);
|
|
377
|
-
g.n = COL_SIZE(nb);
|
|
425
|
+
g.m = gemm_int(ROW_SIZE(na), "row size of a");
|
|
426
|
+
g.k = gemm_int(COL_SIZE(na), "column size of a");
|
|
427
|
+
g.n = gemm_int(COL_SIZE(nb), "column size of b");
|
|
378
428
|
|
|
379
429
|
// The batch dimensions reach cuBLAS as one stride per operand, so both
|
|
380
430
|
// operands must hold the same number of matrices. An operand holding a
|
|
@@ -402,16 +452,17 @@ static VALUE
|
|
|
402
452
|
CumoGetNArray(c, nc);
|
|
403
453
|
CHECK_DIM_GE(nc, 2);
|
|
404
454
|
if (ROW_SIZE(nc) != ROW_SIZE(na)) {
|
|
405
|
-
rb_raise(cumo_na_eShapeError,"ROW_SIZE(c)=%
|
|
406
|
-
|
|
455
|
+
rb_raise(cumo_na_eShapeError,"ROW_SIZE(c)=%"SZF"u must equal to ROW_SIZE(a)=%"SZF"u",
|
|
456
|
+
ROW_SIZE(nc), ROW_SIZE(na));
|
|
407
457
|
}
|
|
408
458
|
if (COL_SIZE(nc) != COL_SIZE(nb)) {
|
|
409
|
-
rb_raise(cumo_na_eShapeError,"COL_SIZE(c)=%
|
|
410
|
-
|
|
459
|
+
rb_raise(cumo_na_eShapeError,"COL_SIZE(c)=%"SZF"u must equal to COL_SIZE(b)=%"SZF"u",
|
|
460
|
+
COL_SIZE(nc), COL_SIZE(nb));
|
|
411
461
|
}
|
|
412
|
-
|
|
462
|
+
int c_batch = gemm_batch_count(nc);
|
|
463
|
+
if (c_batch != batch) {
|
|
413
464
|
rb_raise(cumo_na_eShapeError,"batch count of c=%d must equal to %d",
|
|
414
|
-
|
|
465
|
+
c_batch, batch);
|
|
415
466
|
}
|
|
416
467
|
// a and b are duplicated when they are not contiguous, but c is written
|
|
417
468
|
// in place, and cuBLAS writes it as ldc=n stridec=m*n from its offset
|
|
@@ -9,13 +9,6 @@
|
|
|
9
9
|
rb_define_const(<%=ns_var%>, "<%=x%>", <%=type_var%>);
|
|
10
10
|
<% end %>
|
|
11
11
|
|
|
12
|
-
hCast = rb_hash_new();
|
|
13
|
-
rb_define_const(cT, "UPCAST", hCast);
|
|
14
|
-
rb_hash_aset(hCast, rb_cArray, cT);
|
|
15
|
-
<% for x in upcast %>
|
|
16
|
-
<%= x %><% end %>
|
|
17
|
-
rb_obj_freeze(hCast);
|
|
18
|
-
|
|
19
12
|
<% @children.each do |m| %>
|
|
20
13
|
<%= m.init_def %><% end %>
|
|
21
14
|
rb_define_singleton_method(cT, "[]", <%=find("cast").c_func%>, -2);
|
|
@@ -17,6 +17,6 @@ static VALUE
|
|
|
17
17
|
<%=c_func(0)%>(VALUE ary)
|
|
18
18
|
{
|
|
19
19
|
CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
20
|
-
|
|
20
|
+
cumo_cuda_runtime_device_synchronize();
|
|
21
21
|
return cumo_na_ndloop_inspect(ary, <%=c_iter%>, Qnil);
|
|
22
22
|
}
|
|
@@ -37,7 +37,7 @@ extern VALUE cRT;
|
|
|
37
37
|
void
|
|
38
38
|
Init_<%=lib_name%>(void)
|
|
39
39
|
{
|
|
40
|
-
VALUE
|
|
40
|
+
VALUE <%=ns_var%>;
|
|
41
41
|
|
|
42
42
|
<%=ns_var%> = rb_define_module("Cumo");
|
|
43
43
|
|
|
@@ -48,3 +48,13 @@ Init_<%=lib_name%>(void)
|
|
|
48
48
|
<%= c.init_def %>
|
|
49
49
|
<% end %>
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
// cumo.c runs this after the last Init_cumo_*. Any class defined after this
|
|
53
|
+
// one is still 0 during Init, and its entry would land under the key false.
|
|
54
|
+
void
|
|
55
|
+
Init_<%=lib_name%>_upcast(void)
|
|
56
|
+
{
|
|
57
|
+
VALUE hCast;
|
|
58
|
+
|
|
59
|
+
<% children.each do |c| %><%= c.upcast_def %><% end %>
|
|
60
|
+
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
static inline dtype
|
|
2
2
|
yield_map_with_index(dtype x, size_t *c, VALUE *a, int nd, int md)
|
|
3
3
|
{
|
|
4
|
-
|
|
5
|
-
VALUE y;
|
|
6
|
-
|
|
7
|
-
a[0] = m_data_to_num(x);
|
|
8
|
-
for (j=0; j<=nd; j++) {
|
|
9
|
-
a[j+1] = SIZET2NUM(c[j]);
|
|
10
|
-
}
|
|
11
|
-
y = rb_yield(rb_ary_new4(md,a));
|
|
12
|
-
return m_num_to_data(y);
|
|
4
|
+
return m_num_to_data(cumo_na_yield_with_index(m_data_to_num(x),c,a,nd,md));
|
|
13
5
|
}
|
|
14
6
|
|
|
15
7
|
static void
|
|
@@ -25,17 +17,14 @@ static void
|
|
|
25
17
|
int nd, md;
|
|
26
18
|
|
|
27
19
|
c = (size_t*)(lp->opt_ptr);
|
|
28
|
-
|
|
29
|
-
if (nd > 0) {nd--;}
|
|
30
|
-
md = nd + 2;
|
|
20
|
+
cumo_na_with_index_dims(lp->ndim, &nd, &md);
|
|
31
21
|
a = ALLOCA_N(VALUE,md);
|
|
32
22
|
|
|
33
23
|
CUMO_INIT_COUNTER(lp, i);
|
|
34
24
|
CUMO_INIT_PTR_IDX(lp, 0, p1, s1, idx1);
|
|
35
25
|
CUMO_INIT_PTR_IDX(lp, 1, p2, s2, idx2);
|
|
36
26
|
|
|
37
|
-
CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
38
|
-
cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
|
|
27
|
+
if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
|
|
39
28
|
|
|
40
29
|
c[nd] = 0;
|
|
41
30
|
if (idx1) {
|
|
@@ -43,6 +32,7 @@ static void
|
|
|
43
32
|
for (; i--;) {
|
|
44
33
|
CUMO_GET_DATA_INDEX(p1,idx1,dtype,x);
|
|
45
34
|
x = yield_map_with_index(x,c,a,nd,md);
|
|
35
|
+
if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
|
|
46
36
|
CUMO_SET_DATA_INDEX(p2,idx2,dtype,x);
|
|
47
37
|
c[nd]++;
|
|
48
38
|
}
|
|
@@ -50,6 +40,7 @@ static void
|
|
|
50
40
|
for (; i--;) {
|
|
51
41
|
CUMO_GET_DATA_INDEX(p1,idx1,dtype,x);
|
|
52
42
|
x = yield_map_with_index(x,c,a,nd,md);
|
|
43
|
+
if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
|
|
53
44
|
CUMO_SET_DATA_STRIDE(p2,s2,dtype,x);
|
|
54
45
|
c[nd]++;
|
|
55
46
|
}
|
|
@@ -59,6 +50,7 @@ static void
|
|
|
59
50
|
for (; i--;) {
|
|
60
51
|
CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
|
|
61
52
|
x = yield_map_with_index(x,c,a,nd,md);
|
|
53
|
+
if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
|
|
62
54
|
CUMO_SET_DATA_INDEX(p2,idx2,dtype,x);
|
|
63
55
|
c[nd]++;
|
|
64
56
|
}
|
|
@@ -66,6 +58,7 @@ static void
|
|
|
66
58
|
for (; i--;) {
|
|
67
59
|
CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
|
|
68
60
|
x = yield_map_with_index(x,c,a,nd,md);
|
|
61
|
+
if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
|
|
69
62
|
CUMO_SET_DATA_STRIDE(p2,s2,dtype,x);
|
|
70
63
|
c[nd]++;
|
|
71
64
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
void cumo_<%=type_name%>_median_kernel_launch(cumo_na_reduction_arg_t* arg, int flat);
|
|
1
|
+
void cumo_<%=type_name%>_median_kernel_launch(cumo_na_reduction_arg_t* arg, int flat, int prnan);
|
|
2
2
|
|
|
3
3
|
// The rows are sorted with one cub call and the middle of each is picked by a
|
|
4
|
-
// kernel of its own.
|
|
5
|
-
//
|
|
4
|
+
// kernel of its own. The sort keys put every NaN last, so nan:true only has to
|
|
5
|
+
// notice that one is there.
|
|
6
|
+
<% (is_float ? ["_ignan","_prnan"] : [""]).each do |j| %>
|
|
6
7
|
static void
|
|
7
|
-
<%=c_iter%>
|
|
8
|
+
<%=c_iter%><%=j%>(cumo_na_loop_t *const lp)
|
|
8
9
|
{
|
|
9
10
|
cumo_na_reduction_arg_t arg = cumo_na_make_reduction_arg(lp, 1);
|
|
10
11
|
ssize_t expect = sizeof(dtype);
|
|
@@ -19,41 +20,7 @@ static void
|
|
|
19
20
|
expect *= (ssize_t)arg.in_indexer.shape[i];
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
cumo_<%=type_name%>_median_kernel_launch(&arg, flat);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
<% (is_float ? ["_ignan","_prnan"] : [""]).each do |j| %>
|
|
26
|
-
static void
|
|
27
|
-
<%=c_iter%><%=j%>(cumo_na_loop_t *const lp)
|
|
28
|
-
{
|
|
29
|
-
size_t n;
|
|
30
|
-
char *p1, *p2;
|
|
31
|
-
dtype *buf;
|
|
32
|
-
|
|
33
|
-
CUMO_INIT_COUNTER(lp, n);
|
|
34
|
-
p1 = (lp->args[0]).ptr + (lp->args[0].iter[0]).pos;
|
|
35
|
-
p2 = (lp->args[1]).ptr + (lp->args[1].iter[0]).pos;
|
|
36
|
-
buf = (dtype*)p1;
|
|
37
|
-
|
|
38
|
-
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%><%=j%>", "<%=type_name%>");
|
|
39
|
-
cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
|
|
40
|
-
<%=type_name%>_qsort<%=j%>(buf, n, sizeof(dtype));
|
|
41
|
-
|
|
42
|
-
<% if is_float %>
|
|
43
|
-
for (; n; n--) {
|
|
44
|
-
if (!isnan(buf[n-1])) break;
|
|
45
|
-
}
|
|
46
|
-
<% end %>
|
|
47
|
-
|
|
48
|
-
if (n==0) {
|
|
49
|
-
*(dtype*)p2 = buf[0];
|
|
50
|
-
}
|
|
51
|
-
else if (n%2==0) {
|
|
52
|
-
*(dtype*)p2 = (buf[n/2-1]+buf[n/2])/2;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
*(dtype*)p2 = buf[(n-1)/2];
|
|
56
|
-
}
|
|
23
|
+
cumo_<%=type_name%>_median_kernel_launch(&arg, flat, <%= j == "_prnan" ? 1 : 0 %>);
|
|
57
24
|
}
|
|
58
25
|
<% end %>
|
|
59
26
|
|
|
@@ -82,18 +49,13 @@ static VALUE
|
|
|
82
49
|
<% if is_float %>
|
|
83
50
|
ndf.func = <%=c_iter%>_ignan;
|
|
84
51
|
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, <%=c_iter%>_prnan);
|
|
85
|
-
if (ndf.func == <%=c_iter%>_ignan) {
|
|
86
|
-
ndf.func = <%=c_iter%>_kernel;
|
|
87
|
-
// or rather than assign: cumo_na_reduce_dimension may have set
|
|
88
|
-
// CUMO_NDF_KEEP_DIM by then, and assigning would drop it
|
|
89
|
-
ndf.flag |= CUMO_NDF_STRIDE_LOOP|CUMO_NDF_INDEXER_LOOP;
|
|
90
|
-
}
|
|
91
52
|
<% else %>
|
|
92
53
|
ndf.func = <%=c_iter%>;
|
|
93
54
|
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
94
|
-
ndf.func = <%=c_iter%>_kernel;
|
|
95
|
-
ndf.flag |= CUMO_NDF_STRIDE_LOOP|CUMO_NDF_INDEXER_LOOP;
|
|
96
55
|
<% end %>
|
|
56
|
+
// or rather than assign: cumo_na_reduce_dimension may have set
|
|
57
|
+
// CUMO_NDF_KEEP_DIM by then, and assigning would drop it
|
|
58
|
+
ndf.flag |= CUMO_NDF_STRIDE_LOOP|CUMO_NDF_INDEXER_LOOP;
|
|
97
59
|
v = cumo_na_ndloop(&ndf, 2, self, reduce);
|
|
98
60
|
return <%=type_name%>_extract(v);
|
|
99
61
|
}
|
|
@@ -20,7 +20,7 @@ static void
|
|
|
20
20
|
CUMO_INIT_PTR(lp, 0, p1, s1);
|
|
21
21
|
|
|
22
22
|
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%><%=j%>", "<%=type_name%>");
|
|
23
|
-
|
|
23
|
+
cumo_cuda_runtime_device_synchronize();
|
|
24
24
|
f_<%=name%><%=j%>(n,p1,s1,&xmin,&xmax);
|
|
25
25
|
|
|
26
26
|
*(dtype*)(lp->args[1].ptr + lp->args[1].iter[0].pos) = xmin;
|
|
@@ -27,7 +27,7 @@ static void
|
|
|
27
27
|
dtype x, y, a;
|
|
28
28
|
|
|
29
29
|
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
|
|
30
|
-
|
|
30
|
+
cumo_cuda_runtime_device_synchronize();
|
|
31
31
|
n = lp->narg - 2;
|
|
32
32
|
x = *(dtype*)CUMO_NDL_PTR(lp,0);
|
|
33
33
|
y = *(dtype*)CUMO_NDL_PTR(lp,n);
|
|
@@ -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
|
// gy = x.pooling_backward(mode, y, kernel_size, stride: 1, pad: 0)
|
|
@@ -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, y, gy, mode, kernel_size, stride, pad, gx;
|
|
32
20
|
VALUE kw_hash = Qnil;
|