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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -2
  3. data/README.md +133 -0
  4. data/bench/cumo_sync_probe.rb +71 -8
  5. data/ext/cumo/cuda/cublas.c +0 -40
  6. data/ext/cumo/cuda/cudnn.c +48 -0
  7. data/ext/cumo/cuda/cudnn_impl.cpp +91 -62
  8. data/ext/cumo/cuda/runtime.c +3 -4
  9. data/ext/cumo/cumo.c +34 -0
  10. data/ext/cumo/extconf.rb +2 -0
  11. data/ext/cumo/include/cumo/cuda/cudnn.h +21 -2
  12. data/ext/cumo/include/cumo/cuda/cumo_thrust.hpp +1 -0
  13. data/ext/cumo/include/cumo/cuda/runtime.h +28 -0
  14. data/ext/cumo/include/cumo/intern.h +4 -1
  15. data/ext/cumo/include/cumo/narray.h +59 -3
  16. data/ext/cumo/include/cumo/template.h +35 -10
  17. data/ext/cumo/include/cumo/template_kernel.h +96 -0
  18. data/ext/cumo/include/cumo/types/bit.h +3 -0
  19. data/ext/cumo/include/cumo/types/bit_kernel.h +3 -0
  20. data/ext/cumo/include/cumo/types/complex_macro.h +2 -0
  21. data/ext/cumo/include/cumo/types/complex_macro_kernel.h +2 -0
  22. data/ext/cumo/include/cumo/types/float_macro.h +2 -0
  23. data/ext/cumo/include/cumo/types/float_macro_kernel.h +2 -0
  24. data/ext/cumo/include/cumo/types/half_def.h +129 -0
  25. data/ext/cumo/include/cumo/types/half_def_kernel.h +28 -0
  26. data/ext/cumo/include/cumo/types/half_macro.h +188 -0
  27. data/ext/cumo/include/cumo/types/half_macro_kernel.h +198 -0
  28. data/ext/cumo/include/cumo/types/hfloat.h +22 -0
  29. data/ext/cumo/include/cumo/types/hfloat_kernel.h +16 -0
  30. data/ext/cumo/include/cumo/types/real_accum.h +2 -0
  31. data/ext/cumo/include/cumo/types/real_accum_kernel.h +2 -0
  32. data/ext/cumo/include/cumo/types/robj_macro.h +3 -0
  33. data/ext/cumo/include/cumo/types/xint_macro.h +3 -0
  34. data/ext/cumo/include/cumo/types/xint_macro_kernel.h +2 -0
  35. data/ext/cumo/include/cumo.h +2 -2
  36. data/ext/cumo/narray/data.c +49 -174
  37. data/ext/cumo/narray/gen/def/bit.rb +2 -0
  38. data/ext/cumo/narray/gen/def/dcomplex.rb +2 -0
  39. data/ext/cumo/narray/gen/def/dfloat.rb +8 -0
  40. data/ext/cumo/narray/gen/def/hfloat.rb +47 -0
  41. data/ext/cumo/narray/gen/def/int16.rb +2 -0
  42. data/ext/cumo/narray/gen/def/int32.rb +2 -0
  43. data/ext/cumo/narray/gen/def/int64.rb +2 -0
  44. data/ext/cumo/narray/gen/def/int8.rb +2 -0
  45. data/ext/cumo/narray/gen/def/robject.rb +2 -0
  46. data/ext/cumo/narray/gen/def/scomplex.rb +2 -0
  47. data/ext/cumo/narray/gen/def/sfloat.rb +8 -0
  48. data/ext/cumo/narray/gen/def/uint16.rb +3 -1
  49. data/ext/cumo/narray/gen/def/uint32.rb +3 -1
  50. data/ext/cumo/narray/gen/def/uint64.rb +2 -0
  51. data/ext/cumo/narray/gen/def/uint8.rb +3 -1
  52. data/ext/cumo/narray/gen/erbpp2.rb +6 -0
  53. data/ext/cumo/narray/gen/spec.rb +1 -0
  54. data/ext/cumo/narray/gen/tmpl/accum.c +1 -1
  55. data/ext/cumo/narray/gen/tmpl/accum_arg.c +1 -1
  56. data/ext/cumo/narray/gen/tmpl/accum_arg_kernel.cu +5 -5
  57. data/ext/cumo/narray/gen/tmpl/accum_binary_kernel.cu +14 -1
  58. data/ext/cumo/narray/gen/tmpl/accum_index.c +1 -1
  59. data/ext/cumo/narray/gen/tmpl/accum_index_kernel.cu +5 -5
  60. data/ext/cumo/narray/gen/tmpl/alloc_func.c +4 -7
  61. data/ext/cumo/narray/gen/tmpl/allocate.c +1 -2
  62. data/ext/cumo/narray/gen/tmpl/aref_cpu.c +1 -1
  63. data/ext/cumo/narray/gen/tmpl/batch_norm.c +11 -23
  64. data/ext/cumo/narray/gen/tmpl/batch_norm_backward.c +12 -24
  65. data/ext/cumo/narray/gen/tmpl/binary_kernel.cu +69 -2
  66. data/ext/cumo/narray/gen/tmpl/clip.c +3 -3
  67. data/ext/cumo/narray/gen/tmpl/cond_unary.c +1 -1
  68. data/ext/cumo/narray/gen/tmpl/conv.c +11 -17
  69. data/ext/cumo/narray/gen/tmpl/conv_grad_w.c +11 -17
  70. data/ext/cumo/narray/gen/tmpl/conv_transpose.c +11 -17
  71. data/ext/cumo/narray/gen/tmpl/cum.c +24 -1
  72. data/ext/cumo/narray/gen/tmpl/cum_kernel.cu +29 -4
  73. data/ext/cumo/narray/gen/tmpl/each.c +2 -3
  74. data/ext/cumo/narray/gen/tmpl/each_with_index.c +5 -21
  75. data/ext/cumo/narray/gen/tmpl/extract_cpu.c +1 -1
  76. data/ext/cumo/narray/gen/tmpl/extract_data.c +1 -1
  77. data/ext/cumo/narray/gen/tmpl/fill.c +1 -1
  78. data/ext/cumo/narray/gen/tmpl/fixed_batch_norm.c +9 -21
  79. data/ext/cumo/narray/gen/tmpl/float_accum_kernel.cu +42 -37
  80. data/ext/cumo/narray/gen/tmpl/format.c +1 -1
  81. data/ext/cumo/narray/gen/tmpl/format_to_a.c +1 -1
  82. data/ext/cumo/narray/gen/tmpl/gemm.c +78 -27
  83. data/ext/cumo/narray/gen/tmpl/init_class.c +0 -7
  84. data/ext/cumo/narray/gen/tmpl/init_upcast.c +6 -0
  85. data/ext/cumo/narray/gen/tmpl/inspect.c +1 -1
  86. data/ext/cumo/narray/gen/tmpl/lib.c +11 -1
  87. data/ext/cumo/narray/gen/tmpl/map_with_index.c +7 -14
  88. data/ext/cumo/narray/gen/tmpl/median.c +9 -47
  89. data/ext/cumo/narray/gen/tmpl/minmax.c +1 -1
  90. data/ext/cumo/narray/gen/tmpl/poly.c +1 -1
  91. data/ext/cumo/narray/gen/tmpl/pooling_backward.c +2 -14
  92. data/ext/cumo/narray/gen/tmpl/pooling_forward.c +2 -14
  93. data/ext/cumo/narray/gen/tmpl/qsort.c +0 -1
  94. data/ext/cumo/narray/gen/tmpl/rand.c +20 -2
  95. data/ext/cumo/narray/gen/tmpl/rand_kernel.cu +13 -0
  96. data/ext/cumo/narray/gen/tmpl/rand_norm.c +4 -4
  97. data/ext/cumo/narray/gen/tmpl/rand_norm_kernel.cu +7 -5
  98. data/ext/cumo/narray/gen/tmpl/real_accum_kernel.cu +83 -97
  99. data/ext/cumo/narray/gen/tmpl/sort.c +1 -1
  100. data/ext/cumo/narray/gen/tmpl/sort_index.c +6 -3
  101. data/ext/cumo/narray/gen/tmpl/store_array.c +21 -22
  102. data/ext/cumo/narray/gen/tmpl/store_bit.c +1 -1
  103. data/ext/cumo/narray/gen/tmpl/store_from.c +1 -1
  104. data/ext/cumo/narray/gen/tmpl/store_from_kernel.cu +37 -2
  105. data/ext/cumo/narray/gen/tmpl/to_a.c +1 -1
  106. data/ext/cumo/narray/gen/tmpl/unary.c +20 -3
  107. data/ext/cumo/narray/gen/tmpl/unary2.c +1 -1
  108. data/ext/cumo/narray/gen/tmpl/unary_s.c +1 -1
  109. data/ext/cumo/narray/gen/tmpl_bit/allocate.c +2 -3
  110. data/ext/cumo/narray/gen/tmpl_bit/aref_cpu.c +1 -1
  111. data/ext/cumo/narray/gen/tmpl_bit/bit_count_cpu.c +1 -1
  112. data/ext/cumo/narray/gen/tmpl_bit/each.c +2 -2
  113. data/ext/cumo/narray/gen/tmpl_bit/each_with_index.c +5 -20
  114. data/ext/cumo/narray/gen/tmpl_bit/extract_cpu.c +1 -1
  115. data/ext/cumo/narray/gen/tmpl_bit/format.c +1 -1
  116. data/ext/cumo/narray/gen/tmpl_bit/format_to_a.c +1 -1
  117. data/ext/cumo/narray/gen/tmpl_bit/inspect.c +1 -1
  118. data/ext/cumo/narray/gen/tmpl_bit/mask.c +38 -17
  119. data/ext/cumo/narray/gen/tmpl_bit/mask_kernel.cu +4 -4
  120. data/ext/cumo/narray/gen/tmpl_bit/store_array.c +10 -11
  121. data/ext/cumo/narray/gen/tmpl_bit/store_from.c +1 -1
  122. data/ext/cumo/narray/gen/tmpl_bit/to_a.c +1 -1
  123. data/ext/cumo/narray/gen/tmpl_bit/where.c +66 -13
  124. data/ext/cumo/narray/gen/tmpl_bit/where2.c +57 -20
  125. data/ext/cumo/narray/gen/tmpl_bit/where_kernel.cu +6 -6
  126. data/ext/cumo/narray/index.c +63 -18
  127. data/ext/cumo/narray/index_kernel.cu +15 -0
  128. data/ext/cumo/narray/math.c +2 -0
  129. data/ext/cumo/narray/narray.c +289 -183
  130. data/ext/cumo/narray/ndloop.c +91 -26
  131. data/ext/cumo/narray/sort_kernel.cu +39 -18
  132. data/ext/cumo/narray/struct.c +14 -17
  133. data/lib/cumo/cuda/cudnn.rb +1 -1
  134. data/lib/cumo/narray/extra.rb +11 -2
  135. data/test/bit_test.rb +147 -0
  136. data/test/cudnn_test.rb +132 -46
  137. data/test/extra_test.rb +1 -1
  138. data/test/hfloat_test.rb +717 -0
  139. data/test/math_test.rb +4 -1
  140. data/test/narray_alt_coverage_test.rb +7 -0
  141. data/test/narray_test.rb +1018 -11
  142. data/test/test_helper.rb +73 -0
  143. 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
  // gx, ggamma, gbeta = x.batch_norm_backward(gamma, gy, mean:, inv_std:, eps:, axis:)
17
5
  static VALUE
@@ -20,8 +8,8 @@ static VALUE
20
8
  cudnnDataType_t cudnn_dtype = <%= cudnn_dtype %>;
21
9
  cudnnStatus_t status = 0;
22
10
  cudnnHandle_t handle = 0;
23
- dtype coef_one = 1;
24
- dtype coef_zero = 0;
11
+ <%=cudnn_scalar_t%> coef_one = 1;
12
+ <%=cudnn_scalar_t%> coef_zero = 0;
25
13
 
26
14
  VALUE x=self, gamma, gy, mean, inv_std, eps, axis, gx, ggamma, gbeta;
27
15
  VALUE kw_hash = Qnil;
@@ -107,10 +95,10 @@ static VALUE
107
95
  }
108
96
 
109
97
  CUMO_CHECK_NARRAY_TYPE(x, cT);
110
- CUMO_CHECK_NARRAY_TYPE(gamma, cT);
98
+ cumo_cuda_cudnn_check_param_type(gamma, <%=cudnn_param_class%>, "gamma");
111
99
  CUMO_CHECK_NARRAY_TYPE(gy, cT);
112
- if (mean != Qnil) CUMO_CHECK_NARRAY_TYPE(mean, cT);
113
- if (inv_std != Qnil) CUMO_CHECK_NARRAY_TYPE(inv_std, cT);
100
+ if (mean != Qnil) cumo_cuda_cudnn_check_param_type(mean, <%=cudnn_param_class%>, "mean");
101
+ if (inv_std != Qnil) cumo_cuda_cudnn_check_param_type(inv_std, <%=cudnn_param_class%>, "inv_std");
114
102
 
115
103
  x_cont = cumo_na_as_contiguous_array(x);
116
104
  gamma_cont = cumo_na_as_contiguous_array(gamma);
@@ -133,15 +121,15 @@ static VALUE
133
121
  }
134
122
  gx_ptr = cumo_na_get_offset_pointer_for_write(gx);
135
123
  if (ggamma == Qnil) {
136
- ggamma = cumo_na_new(cT, gamma_ndim, gamma_shape);
124
+ ggamma = cumo_na_new(<%=cudnn_param_class%>, gamma_ndim, gamma_shape);
137
125
  } else {
138
- cumo_cuda_cudnn_check_output(ggamma, cT, gamma_ndim, gamma_shape);
126
+ cumo_cuda_cudnn_check_output(ggamma, <%=cudnn_param_class%>, gamma_ndim, gamma_shape);
139
127
  }
140
128
  ggamma_ptr = cumo_na_get_offset_pointer_for_write(ggamma);
141
129
  if (gbeta == Qnil) {
142
- gbeta = cumo_na_new(cT, gamma_ndim, gamma_shape);
130
+ gbeta = cumo_na_new(<%=cudnn_param_class%>, gamma_ndim, gamma_shape);
143
131
  } else {
144
- cumo_cuda_cudnn_check_output(gbeta, cT, gamma_ndim, gamma_shape);
132
+ cumo_cuda_cudnn_check_output(gbeta, <%=cudnn_param_class%>, gamma_ndim, gamma_shape);
145
133
  }
146
134
  gbeta_ptr = cumo_na_get_offset_pointer_for_write(gbeta);
147
135
 
@@ -151,9 +139,9 @@ static VALUE
151
139
  mode = cumo_cuda_cudnn_GetBatchNormMode(axis_ndim, int_axis);
152
140
  status = cumo_cuda_cudnn_CreateBNTensorDescriptor(&bn_desc, x_desc, mode);
153
141
  if (status != CUDNN_STATUS_SUCCESS) goto BATCH_NORM_BACKWARD_ERROR;
154
- // The derived descriptor carries x's own type -- cuDNN widens only for
155
- // half, which these templates are never generated for -- and the checks
156
- // above hold every parameter to x's class, so none of them needs a cast.
142
+ // cuDNN derives the parameter descriptor as float for a half x and as x's
143
+ // own type otherwise, and the checks above hold every parameter to exactly
144
+ // that class, so none of them needs a cast.
157
145
 
158
146
  handle = cumo_cuda_cudnn_handle();
159
147
 
@@ -48,6 +48,64 @@ __global__ void <%="cumo_#{c_iter}_kernel_dim#{idim}"%>(cumo_na_iarray_t a1, cum
48
48
  //<% end %>
49
49
  <% end %>
50
50
 
51
+ // One operand of a 2-d elementwise op can be a transposed view, which leaves
52
+ // either its read or the write strided whichever way the loop walks. Stage that
53
+ // operand through a shared memory tile so all three arrays are touched in rows.
54
+ // t_side says which operand is the transposed one.
55
+ __global__ void <%="cumo_#{c_iter}_transpose_kernel"%>(char *p1, char *p2, char *p3, int* divzero, int t_side, uint64_t rows, uint64_t cols)
56
+ {
57
+ CUMO_TRANSPOSE_TILE_DECL(dtype, tile);
58
+ char *tp = (t_side == 1) ? p1 : p2;
59
+ char *sp = (t_side == 1) ? p2 : p1;
60
+
61
+ CUMO_TRANSPOSE_TILE_LOOP(tile, rows, cols,
62
+ *(dtype*)(tp + cumo_tile_src * sizeof(dtype)),
63
+ dtype o = *(dtype*)(sp + cumo_tile_dst * sizeof(dtype));
64
+ dtype lhs = (t_side == 1) ? cumo_tile_val : o;
65
+ dtype rhs = (t_side == 1) ? o : cumo_tile_val;
66
+ cumo_check_intdivzero(rhs);
67
+ *(dtype*)(p3 + cumo_tile_dst * sizeof(dtype)) = m_<%=name%>(lhs, rhs);
68
+ );
69
+ }
70
+
71
+ // Launches the tiled kernel and answers 1 when it did. It takes over when one
72
+ // operand is a transposed plain array and the other two are row-major ones, and
73
+ // only once both sides reach a tile: a shorter one leaves most of each warp idle
74
+ // while the plain loop already reads or writes it in one go.
75
+ static int
76
+ <%="cumo_#{c_iter}_launch_transpose"%>(cumo_na_iarray_t* a1, cumo_na_iarray_t* a2, cumo_na_iarray_t* a3, cumo_na_indexer_t* indexer, int* divzero)
77
+ {
78
+ ssize_t esz = (ssize_t)sizeof(dtype);
79
+ uint64_t rows, cols;
80
+ ssize_t row, col;
81
+ int rows_a1, rows_a2, t_side;
82
+
83
+ if (!CUMO_TRANSPOSE_TILE_FITS(indexer)) {
84
+ return 0;
85
+ }
86
+ rows = indexer->shape[0];
87
+ cols = indexer->shape[1];
88
+ row = esz * (ssize_t)cols;
89
+ col = esz * (ssize_t)rows;
90
+ if (a3->step[0] != row || a3->step[1] != esz) {
91
+ return 0;
92
+ }
93
+ rows_a1 = (a1->step[0] == row && a1->step[1] == esz);
94
+ rows_a2 = (a2->step[0] == row && a2->step[1] == esz);
95
+ if (!rows_a2 && rows_a1 && a2->step[0] == esz && a2->step[1] == col) {
96
+ t_side = 2;
97
+ } else if (!rows_a1 && rows_a2 && a1->step[0] == esz && a1->step[1] == col) {
98
+ t_side = 1;
99
+ } else {
100
+ return 0;
101
+ }
102
+
103
+ CUMO_TRANSPOSE_LAUNCH(<%="cumo_#{c_iter}_transpose_kernel"%>, rows, cols,
104
+ a1->ptr, a2->ptr, a3->ptr, divzero, t_side);
105
+ cumo_cuda_runtime_check_kernel_launch();
106
+ return 1;
107
+ }
108
+
51
109
  //<% if has_scalar %>
52
110
  static void <%="cumo_#{c_iter}_kernel_dispatch"%>(cumo_na_iarray_t* a1, cumo_na_iarray_t* a2, cumo_na_iarray_t* a3, cumo_na_indexer_t* indexer, int* divzero, dtype sv, int use_scalar)
53
111
  {
@@ -69,6 +127,10 @@ static void <%="cumo_#{c_iter}_kernel_dispatch"%>(cumo_na_iarray_t* a1, cumo_na_
69
127
  void <%="cumo_#{c_iter}_kernel_launch"%>(cumo_na_iarray_t* a1, cumo_na_iarray_t* a2, cumo_na_iarray_t* a3, cumo_na_indexer_t* indexer, int* divzero)
70
128
  {
71
129
  dtype sv;
130
+
131
+ if (<%="cumo_#{c_iter}_launch_transpose"%>(a1,a2,a3,indexer,divzero)) {
132
+ return;
133
+ }
72
134
  memset(&sv, 0, sizeof(dtype));
73
135
  <%="cumo_#{c_iter}_kernel_dispatch"%>(a1,a2,a3,indexer,divzero,sv,0);
74
136
  }
@@ -82,8 +144,13 @@ void <%="cumo_#{c_iter}_s_kernel_launch"%>(cumo_na_iarray_t* a1, dtype sv, cumo_
82
144
  //<% else %>
83
145
  void <%="cumo_#{c_iter}_kernel_launch"%>(cumo_na_iarray_t* a1, cumo_na_iarray_t* a2, cumo_na_iarray_t* a3, cumo_na_indexer_t* indexer, int* divzero)
84
146
  {
85
- size_t grid_dim = cumo_get_grid_dim(indexer->total_size);
86
- size_t block_dim = cumo_get_block_dim(indexer->total_size);
147
+ size_t grid_dim, block_dim;
148
+
149
+ if (<%="cumo_#{c_iter}_launch_transpose"%>(a1,a2,a3,indexer,divzero)) {
150
+ return;
151
+ }
152
+ grid_dim = cumo_get_grid_dim(indexer->total_size);
153
+ block_dim = cumo_get_block_dim(indexer->total_size);
87
154
  switch (indexer->ndim) {
88
155
  <% (0..opt_indexer_ndim).each do |idim| %>
89
156
  case <%=idim%>:
@@ -24,7 +24,7 @@ static void
24
24
  CUMO_INIT_PTR(lp, 3, p4, s4);
25
25
 
26
26
  CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
27
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
27
+ cumo_cuda_runtime_device_synchronize();
28
28
  for (i=n; i--;) {
29
29
  CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
30
30
  CUMO_GET_DATA_STRIDE(p2,s2,dtype,min);
@@ -69,7 +69,7 @@ static void
69
69
  CUMO_INIT_PTR(lp, 2, p3, s3);
70
70
 
71
71
  CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>_min", "<%=type_name%>");
72
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
72
+ cumo_cuda_runtime_device_synchronize();
73
73
  for (i=n; i--;) {
74
74
  CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
75
75
  CUMO_GET_DATA_STRIDE(p2,s2,dtype,min);
@@ -105,7 +105,7 @@ static void
105
105
  CUMO_INIT_PTR(lp, 2, p3, s3);
106
106
 
107
107
  CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>_max", "<%=type_name%>");
108
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
108
+ cumo_cuda_runtime_device_synchronize();
109
109
  for (i=n; i--;) {
110
110
  CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
111
111
  CUMO_GET_DATA_STRIDE(p2,s2,dtype,max);
@@ -20,7 +20,7 @@ static void
20
20
  CUMO_INIT_PTR_IDX(lp, 0, p1, s1, idx1);
21
21
  CUMO_INIT_PTR_BIT(lp, 1, a2, p2, s2);
22
22
  CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
23
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
23
+ cumo_cuda_runtime_device_synchronize();
24
24
  if (idx1) {
25
25
  for (i=0; i<n; i++) {
26
26
  CUMO_GET_DATA_INDEX(p1,idx1,dtype,x);
@@ -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
  // dilation > 1 is not supported yet
@@ -22,8 +10,8 @@ static VALUE
22
10
  cudnnDataType_t cudnn_dtype = <%= cudnn_dtype %>;
23
11
  cudnnStatus_t status = 0;
24
12
  cudnnHandle_t handle = 0;
25
- dtype alpha = 1;
26
- dtype beta = 0;
13
+ <%=cudnn_scalar_t%> alpha = 1;
14
+ <%=cudnn_scalar_t%> beta = 0;
27
15
 
28
16
  VALUE x=self, w, b, stride, pad, y;
29
17
  VALUE kw_hash = Qnil;
@@ -45,7 +33,7 @@ static VALUE
45
33
 
46
34
  cudnnConvolutionFwdAlgoPerf_t perf_result;
47
35
  cudnnConvolutionFwdAlgo_t algo;
48
- size_t max_workspace_size = CUMO_CUDA_CUDNN_DEFAULT_MAX_WORKSPACE_SIZE;
36
+ size_t max_workspace_size = cumo_cuda_cudnn_max_workspace_size();
49
37
  size_t workspace_size;
50
38
  char* workspace = 0;
51
39
 
@@ -113,7 +101,7 @@ static VALUE
113
101
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_ERROR;
114
102
  status = cumo_cuda_cudnn_CreateFilterDescriptor(&w_desc, w_cont, cudnn_dtype);
115
103
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_ERROR;
116
- status = cumo_cuda_cudnn_CreateConvolutionDescriptor(&conv_desc, ndim, int_stride, int_pad, cudnn_dtype);
104
+ status = cumo_cuda_cudnn_CreateConvolutionDescriptor(&conv_desc, ndim, int_stride, int_pad, <%=cudnn_compute_dtype%>, <%=cudnn_math_type%>);
117
105
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_ERROR;
118
106
 
119
107
  handle = cumo_cuda_cudnn_handle();
@@ -135,10 +123,16 @@ static VALUE
135
123
  ndim,
136
124
  cudnn_dtype);
137
125
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_ERROR;
126
+ // The descriptor asked for a math type; use the one the search settled on.
127
+ status = cudnnSetConvolutionMathType(conv_desc, perf_result.mathType);
128
+ if (status != CUDNN_STATUS_SUCCESS) goto CONV_ERROR;
129
+
138
130
  algo = perf_result.algo;
139
131
  workspace_size = perf_result.memory;
140
132
 
141
- workspace = cumo_cuda_runtime_malloc(max_workspace_size);
133
+ // The search may look at algorithms needing up to max_workspace_size,
134
+ // but only the one it picked has to be paid for.
135
+ if (workspace_size > 0) workspace = cumo_cuda_runtime_malloc(workspace_size);
142
136
  status = cudnnConvolutionForward(
143
137
  handle,
144
138
  (void*)&alpha,
@@ -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
  static void
17
5
  cumo_cuda_cudnn_get_sizet_ary(size_t *sizet_ary, VALUE ary, size_t ndim)
@@ -31,8 +19,8 @@ static VALUE
31
19
  cudnnDataType_t cudnn_dtype = <%= cudnn_dtype %>;
32
20
  cudnnStatus_t status = 0;
33
21
  cudnnHandle_t handle = 0;
34
- dtype one = 1;
35
- dtype zero = 0;
22
+ <%=cudnn_scalar_t%> one = 1;
23
+ <%=cudnn_scalar_t%> zero = 0;
36
24
 
37
25
  VALUE x=self, gy, w_shape, stride, pad, gw;
38
26
  VALUE kw_hash = Qnil;
@@ -51,7 +39,7 @@ static VALUE
51
39
 
52
40
  cudnnConvolutionBwdFilterAlgoPerf_t perf_result;
53
41
  cudnnConvolutionBwdFilterAlgo_t algo;
54
- size_t max_workspace_size = CUMO_CUDA_CUDNN_DEFAULT_MAX_WORKSPACE_SIZE;
42
+ size_t max_workspace_size = cumo_cuda_cudnn_max_workspace_size();
55
43
  size_t workspace_size;
56
44
  char* workspace = 0;
57
45
 
@@ -124,7 +112,7 @@ static VALUE
124
112
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_GRAD_W_ERROR;
125
113
  status = cumo_cuda_cudnn_CreateFilterDescriptor(&gw_desc, gw, cudnn_dtype);
126
114
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_GRAD_W_ERROR;
127
- status = cumo_cuda_cudnn_CreateConvolutionDescriptor(&conv_desc, ndim, int_stride, int_pad, cudnn_dtype);
115
+ status = cumo_cuda_cudnn_CreateConvolutionDescriptor(&conv_desc, ndim, int_stride, int_pad, <%=cudnn_compute_dtype%>, <%=cudnn_math_type%>);
128
116
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_GRAD_W_ERROR;
129
117
 
130
118
  handle = cumo_cuda_cudnn_handle();
@@ -146,10 +134,16 @@ static VALUE
146
134
  ndim,
147
135
  cudnn_dtype);
148
136
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_GRAD_W_ERROR;
137
+ // The descriptor asked for a math type; use the one the search settled on.
138
+ status = cudnnSetConvolutionMathType(conv_desc, perf_result.mathType);
139
+ if (status != CUDNN_STATUS_SUCCESS) goto CONV_GRAD_W_ERROR;
140
+
149
141
  algo = perf_result.algo;
150
142
  workspace_size = perf_result.memory;
151
143
 
152
- workspace = cumo_cuda_runtime_malloc(max_workspace_size);
144
+ // The search may look at algorithms needing up to max_workspace_size,
145
+ // but only the one it picked has to be paid for.
146
+ if (workspace_size > 0) workspace = cumo_cuda_runtime_malloc(workspace_size);
153
147
  status = cudnnConvolutionBackwardFilter(
154
148
  handle,
155
149
  (void*)&one,
@@ -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
  // VALUE is Ruby Array
17
5
  static void
@@ -47,8 +35,8 @@ static VALUE
47
35
  cudnnDataType_t cudnn_dtype = <%= cudnn_dtype %>;
48
36
  cudnnStatus_t status = 0;
49
37
  cudnnHandle_t handle = 0;
50
- dtype alpha = 1;
51
- dtype beta = 0;
38
+ <%=cudnn_scalar_t%> alpha = 1;
39
+ <%=cudnn_scalar_t%> beta = 0;
52
40
 
53
41
  VALUE x=self, w, b, stride, pad, out_size, y;
54
42
  VALUE kw_hash = Qnil;
@@ -70,7 +58,7 @@ static VALUE
70
58
 
71
59
  cudnnConvolutionBwdDataAlgoPerf_t perf_result;
72
60
  cudnnConvolutionBwdDataAlgo_t algo;
73
- size_t max_workspace_size = CUMO_CUDA_CUDNN_DEFAULT_MAX_WORKSPACE_SIZE;
61
+ size_t max_workspace_size = cumo_cuda_cudnn_max_workspace_size();
74
62
  size_t workspace_size;
75
63
  char* workspace = 0;
76
64
 
@@ -140,7 +128,7 @@ static VALUE
140
128
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_TRANSPOSE_ERROR;
141
129
  status = cumo_cuda_cudnn_CreateFilterDescriptor(&w_desc, w_cont, cudnn_dtype);
142
130
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_TRANSPOSE_ERROR;
143
- status = cumo_cuda_cudnn_CreateConvolutionDescriptor(&conv_desc, ndim, int_stride, int_pad, cudnn_dtype);
131
+ status = cumo_cuda_cudnn_CreateConvolutionDescriptor(&conv_desc, ndim, int_stride, int_pad, <%=cudnn_compute_dtype%>, <%=cudnn_math_type%>);
144
132
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_TRANSPOSE_ERROR;
145
133
 
146
134
  handle = cumo_cuda_cudnn_handle();
@@ -162,10 +150,16 @@ static VALUE
162
150
  ndim,
163
151
  cudnn_dtype);
164
152
  if (status != CUDNN_STATUS_SUCCESS) goto CONV_TRANSPOSE_ERROR;
153
+ // The descriptor asked for a math type; use the one the search settled on.
154
+ status = cudnnSetConvolutionMathType(conv_desc, perf_result.mathType);
155
+ if (status != CUDNN_STATUS_SUCCESS) goto CONV_TRANSPOSE_ERROR;
156
+
165
157
  algo = perf_result.algo;
166
158
  workspace_size = perf_result.memory;
167
159
 
168
- workspace = cumo_cuda_runtime_malloc(max_workspace_size);
160
+ // The search may look at algorithms needing up to max_workspace_size,
161
+ // but only the one it picked has to be paid for.
162
+ if (workspace_size > 0) workspace = cumo_cuda_runtime_malloc(workspace_size);
169
163
  status = cudnnConvolutionBackwardData(
170
164
  handle,
171
165
  (void*)&alpha,
@@ -26,8 +26,30 @@ static void
26
26
  <% end %>
27
27
 
28
28
  CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%><%=j%>", "<%=type_name%>");
29
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
29
+ cumo_cuda_runtime_device_synchronize();
30
30
 
31
+ <% if is_half && name == 'cumsum' %>
32
+ // The scan this stands in for carries float, and a running sum of halves
33
+ // stops moving once it passes 2048, so the accumulator is float here too.
34
+ {
35
+ float acc, fy;
36
+
37
+ CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
38
+ acc = cumo_half2float(x);
39
+ CUMO_SET_DATA_STRIDE(p2,s2,dtype,x);
40
+ for (i--; i--;) {
41
+ CUMO_GET_DATA_STRIDE(p1,s1,dtype,y);
42
+ fy = cumo_half2float(y);
43
+ <% if j == '_nan' %>
44
+ if (acc != acc) { acc = fy; } else if (fy == fy) { acc += fy; }
45
+ <% else %>
46
+ acc += fy;
47
+ <% end %>
48
+ x = cumo_float2half(acc);
49
+ CUMO_SET_DATA_STRIDE(p2,s2,dtype,x);
50
+ }
51
+ }
52
+ <% else %>
31
53
  CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
32
54
  CUMO_SET_DATA_STRIDE(p2,s2,dtype,x);
33
55
  //printf("i=%lu x=%f\n",i,x);
@@ -37,6 +59,7 @@ static void
37
59
  CUMO_SET_DATA_STRIDE(p2,s2,dtype,x);
38
60
  //printf("i=%lu x=%f\n",i,x);
39
61
  }
62
+ <% end %>
40
63
  }
41
64
  <% end %>
42
65
 
@@ -1,4 +1,20 @@
1
1
  <% unless type_name == 'robject' %>
2
+ <% widen = is_half && name == 'cumsum' %>
3
+ <% cum_t = widen ? 'float' : 'dtype' %>
4
+ <% if widen %>
5
+
6
+ // A running sum of halves stops moving once it passes 2048, so the scan carries
7
+ // float and each element is rounded as it is written.
8
+ struct <%="cumo_thrust_#{name}_widen"%>
9
+ {
10
+ __host__ __device__ float operator()(dtype x) const { return cumo_half2float(x); }
11
+ };
12
+
13
+ struct <%="cumo_thrust_#{name}_narrow"%>
14
+ {
15
+ __host__ __device__ dtype operator()(float x) const { return cumo_float2half(x); }
16
+ };
17
+ <% end %>
2
18
  <% (is_float ? ["","_nan"] : [""]).each do |j| %>
3
19
 
4
20
  #if defined(__cplusplus)
@@ -14,12 +30,13 @@
14
30
  // last ulp, the same way sum already does.
15
31
  struct <%="cumo_thrust_#{name}#{j}"%>
16
32
  {
17
- using first_argument_type = dtype;
18
- using second_argument_type = dtype;
19
- using result_type = dtype;
20
- __host__ __device__ dtype operator()(dtype x, dtype y) const { m_<%=name%><%=j%>(x,y); return x; }
33
+ using first_argument_type = <%=cum_t%>;
34
+ using second_argument_type = <%=cum_t%>;
35
+ using result_type = <%=cum_t%>;
36
+ __host__ __device__ <%=cum_t%> operator()(<%=cum_t%> x, <%=cum_t%> y) const { m_<%=name%><%=j%>(x,y); return x; }
21
37
  };
22
38
 
39
+
23
40
  // Nothing may reach the C caller: it has no handler, so an escaping exception
24
41
  // is std::terminate. The status goes back instead and the caller raises.
25
42
  template<typename Iterator1, typename Iterator2>
@@ -27,7 +44,15 @@ static cudaError_t <%="cumo_#{type_name}_#{name}#{j}_scan"%>(Iterator1 first, It
27
44
  {
28
45
  cumo_thrust_pool_allocator alloc;
29
46
  try {
47
+ <% if widen %>
48
+ thrust::inclusive_scan(thrust::cuda::par(alloc),
49
+ thrust::make_transform_iterator(first, <%="cumo_thrust_#{name}_widen"%>()),
50
+ thrust::make_transform_iterator(last, <%="cumo_thrust_#{name}_widen"%>()),
51
+ thrust::make_transform_output_iterator(result, <%="cumo_thrust_#{name}_narrow"%>()),
52
+ <%="cumo_thrust_#{name}#{j}"%>());
53
+ <% else %>
30
54
  thrust::inclusive_scan(thrust::cuda::par(alloc), first, last, result, <%="cumo_thrust_#{name}#{j}"%>());
55
+ <% end %>
31
56
  } catch (const thrust::system_error& e) {
32
57
  return (cudaError_t)e.code().value();
33
58
  } catch (const std::bad_alloc&) {
@@ -10,18 +10,17 @@ static void
10
10
  CUMO_INIT_COUNTER(lp, i);
11
11
  CUMO_INIT_PTR_IDX(lp, 0, p1, s1, idx1);
12
12
 
13
- CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
14
13
 
15
14
  if (idx1) {
16
15
  for (; i--;) {
17
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
16
+ if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
18
17
  CUMO_GET_DATA_INDEX(p1,idx1,dtype,x);
19
18
  y = m_data_to_num(x);
20
19
  rb_yield(y);
21
20
  }
22
21
  } else {
23
22
  for (; i--;) {
24
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
23
+ if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
25
24
  CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
26
25
  y = m_data_to_num(x);
27
26
  rb_yield(y);
@@ -1,16 +1,3 @@
1
- static inline void
2
- yield_each_with_index(dtype x, size_t *c, VALUE *a, int nd, int md)
3
- {
4
- int j;
5
-
6
- a[0] = m_data_to_num(x);
7
- for (j=0; j<=nd; j++) {
8
- a[j+1] = SIZET2NUM(c[j]);
9
- }
10
- rb_yield(rb_ary_new4(md,a));
11
- }
12
-
13
-
14
1
  static void
15
2
  <%=c_iter%>(cumo_na_loop_t *const lp)
16
3
  {
@@ -23,29 +10,26 @@ static void
23
10
  int nd, md;
24
11
 
25
12
  c = (size_t*)(lp->opt_ptr);
26
- nd = lp->ndim;
27
- if (nd > 0) {nd--;}
28
- md = nd + 2;
13
+ cumo_na_with_index_dims(lp->ndim, &nd, &md);
29
14
  a = ALLOCA_N(VALUE,md);
30
15
 
31
16
  CUMO_INIT_COUNTER(lp, i);
32
17
  CUMO_INIT_PTR_IDX(lp, 0, p1, s1, idx1);
33
18
  c[nd] = 0;
34
19
 
35
- CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
36
20
 
37
21
  if (idx1) {
38
22
  for (; i--;) {
39
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
23
+ if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
40
24
  CUMO_GET_DATA_INDEX(p1,idx1,dtype,x);
41
- yield_each_with_index(x,c,a,nd,md);
25
+ cumo_na_yield_with_index(m_data_to_num(x),c,a,nd,md);
42
26
  c[nd]++;
43
27
  }
44
28
  } else {
45
29
  for (; i--;) {
46
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
30
+ if (cumo_cuda_runtime_sync_if_busy()) { CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>"); }
47
31
  CUMO_GET_DATA_STRIDE(p1,s1,dtype,x);
48
- yield_each_with_index(x,c,a,nd,md);
32
+ cumo_na_yield_with_index(m_data_to_num(x),c,a,nd,md);
49
33
  c[nd]++;
50
34
  }
51
35
  }
@@ -17,7 +17,7 @@ static VALUE
17
17
  if (na->ndim==0) {
18
18
  ptr = cumo_na_get_pointer_for_read(self) + cumo_na_get_offset(self);
19
19
  CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
20
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
20
+ cumo_cuda_runtime_device_synchronize();
21
21
  v = m_extract(ptr);
22
22
  cumo_na_release_lock(self);
23
23
  return v;
@@ -12,7 +12,7 @@ static dtype
12
12
  VALUE r, klass;
13
13
 
14
14
  CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("<%=name%>", "<%=type_name%>");
15
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
15
+ cumo_cuda_runtime_device_synchronize();
16
16
 
17
17
  if (CumoIsNArray(obj)) {
18
18
  CumoGetNArray(obj,na);
@@ -19,7 +19,7 @@ static void
19
19
  CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%>", "<%=type_name%>");
20
20
  // The index array is filled by a kernel; wait for it before reading it
21
21
  // from here.
22
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
22
+ cumo_cuda_runtime_device_synchronize();
23
23
  if (idx1) {
24
24
  for (; i--;) {
25
25
  CUMO_SET_DATA_INDEX(p1,idx1,dtype,y);
@@ -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
  // y = x.fixed_batch_norm(gamma, beta, mean, var, eps:, axis:)
17
5
  static VALUE
@@ -20,8 +8,8 @@ static VALUE
20
8
  cudnnDataType_t cudnn_dtype = <%= cudnn_dtype %>;
21
9
  cudnnStatus_t status = 0;
22
10
  cudnnHandle_t handle = 0;
23
- dtype coef_one = 1;
24
- dtype coef_zero = 0;
11
+ <%=cudnn_scalar_t%> coef_one = 1;
12
+ <%=cudnn_scalar_t%> coef_zero = 0;
25
13
 
26
14
  VALUE x=self, gamma, beta, mean, var, eps, axis, y;
27
15
  VALUE kw_hash = Qnil;
@@ -85,10 +73,10 @@ static VALUE
85
73
  }
86
74
 
87
75
  CUMO_CHECK_NARRAY_TYPE(x, cT);
88
- CUMO_CHECK_NARRAY_TYPE(gamma, cT);
89
- CUMO_CHECK_NARRAY_TYPE(beta, cT);
90
- CUMO_CHECK_NARRAY_TYPE(mean, cT);
91
- CUMO_CHECK_NARRAY_TYPE(var, cT);
76
+ cumo_cuda_cudnn_check_param_type(gamma, <%=cudnn_param_class%>, "gamma");
77
+ cumo_cuda_cudnn_check_param_type(beta, <%=cudnn_param_class%>, "beta");
78
+ cumo_cuda_cudnn_check_param_type(mean, <%=cudnn_param_class%>, "mean");
79
+ cumo_cuda_cudnn_check_param_type(var, <%=cudnn_param_class%>, "var");
92
80
 
93
81
  x_cont = cumo_na_as_contiguous_array(x);
94
82
  gamma_cont = cumo_na_as_contiguous_array(gamma);
@@ -115,9 +103,9 @@ static VALUE
115
103
  mode = cumo_cuda_cudnn_GetBatchNormMode(axis_ndim, int_axis);
116
104
  status = cumo_cuda_cudnn_CreateBNTensorDescriptor(&bn_desc, x_desc, mode);
117
105
  if (status != CUDNN_STATUS_SUCCESS) goto FIXED_BATCH_NORM_ERROR;
118
- // The derived descriptor carries x's own type -- cuDNN widens only for
119
- // half, which these templates are never generated for -- and the checks
120
- // above hold every parameter to x's class, so none of them needs a cast.
106
+ // cuDNN derives the parameter descriptor as float for a half x and as x's
107
+ // own type otherwise, and the checks above hold every parameter to exactly
108
+ // that class, so none of them needs a cast.
121
109
 
122
110
  handle = cumo_cuda_cudnn_handle();
123
111