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
@@ -0,0 +1,198 @@
1
+ #ifndef CUMO_HALF_MACRO_KERNEL_H
2
+ #define CUMO_HALF_MACRO_KERNEL_H
3
+
4
+ #include "float_def_kernel.h"
5
+ #include "half_def_kernel.h"
6
+ #include <string.h>
7
+
8
+ #define CUMO_HALF_EPSILON 9.765625e-04f
9
+
10
+ #define m_zero cumo_float2half(0.0f)
11
+ #define m_one cumo_float2half(1.0f)
12
+
13
+ #define m_from_double(x) cumo_double2half((double)(x))
14
+ #define m_from_real(x) cumo_double2half((double)(x))
15
+ #define m_from_sint(x) cumo_double2half((double)(x))
16
+ #define m_from_int32(x) cumo_double2half((double)(x))
17
+ #define m_from_int64(x) cumo_double2half((double)(x))
18
+ #define m_from_uint32(x) cumo_double2half((double)(x))
19
+ #define m_from_uint64(x) cumo_double2half((double)(x))
20
+ #define m_from_half(x) (x)
21
+
22
+ // Overloaded rather than substituted, so that a scan or a reduction can apply
23
+ // the same rule to its own wider accumulator.
24
+ __host__ __device__ static inline float cumo_half_add(float x, float y) { return x + y; }
25
+ __host__ __device__ static inline float cumo_half_sub(float x, float y) { return x - y; }
26
+ __host__ __device__ static inline float cumo_half_mul(float x, float y) { return x * y; }
27
+ __host__ __device__ static inline float cumo_half_div(float x, float y) { return x / y; }
28
+ __host__ __device__ static inline bool cumo_half_not_nan(float x) { return x == x; }
29
+ __host__ __device__ static inline cumo_half cumo_half_add(cumo_half x, cumo_half y) { return cumo_float2half(cumo_half2float(x) + cumo_half2float(y)); }
30
+ __host__ __device__ static inline cumo_half cumo_half_sub(cumo_half x, cumo_half y) { return cumo_float2half(cumo_half2float(x) - cumo_half2float(y)); }
31
+ __host__ __device__ static inline cumo_half cumo_half_mul(cumo_half x, cumo_half y) { return cumo_float2half(cumo_half2float(x) * cumo_half2float(y)); }
32
+ __host__ __device__ static inline cumo_half cumo_half_div(cumo_half x, cumo_half y) { return cumo_float2half(cumo_half2float(x) / cumo_half2float(y)); }
33
+ __host__ __device__ static inline bool cumo_half_not_nan(cumo_half x) { return cumo_half2float(x) == cumo_half2float(x); }
34
+
35
+ #define m_add(x,y) cumo_half_add(x,y)
36
+ #define m_sub(x,y) cumo_half_sub(x,y)
37
+ #define m_mul(x,y) cumo_half_mul(x,y)
38
+ #define m_div(x,y) cumo_half_div(x,y)
39
+ #define m_div_check(x,y) (cumo_half2float(y)==0)
40
+
41
+ __host__ __device__ static inline float cumo_half_floored_mod(float x, float y)
42
+ {
43
+ float r = fmodf(x,y);
44
+ if (r != 0 && ((r < 0) != (y < 0))) {
45
+ r += y;
46
+ }
47
+ return r;
48
+ }
49
+
50
+ #define m_mod(x,y) cumo_float2half(cumo_half_floored_mod(cumo_half2float(x),cumo_half2float(y)))
51
+ #define m_divmod(x,y,a,b) \
52
+ {float cumo_h_x = cumo_half2float(x), cumo_h_y = cumo_half2float(y); \
53
+ float cumo_h_b = fmodf(cumo_h_x,cumo_h_y); \
54
+ float cumo_h_a = roundf((cumo_h_x-cumo_h_b)/cumo_h_y); \
55
+ if (cumo_h_b != 0 && ((cumo_h_b < 0) != (cumo_h_y < 0))) { \
56
+ cumo_h_b += cumo_h_y; cumo_h_a -= 1; \
57
+ } \
58
+ a = cumo_float2half(cumo_h_a); b = cumo_float2half(cumo_h_b);}
59
+ #define m_pow(x,y) cumo_float2half(powf(cumo_half2float(x),cumo_half2float(y)))
60
+ #define m_pow_int(x,y) cumo_float2half(cumo_half_pow_int(cumo_half2float(x),(int)(y)))
61
+
62
+ #define m_abs(x) cumo_float2half(fabsf(cumo_half2float(x)))
63
+ #define m_minus(x) cumo_float2half(-cumo_half2float(x))
64
+ #define m_reciprocal(x) cumo_float2half(1.0f/cumo_half2float(x))
65
+ #define m_square(x) cumo_float2half(cumo_half2float(x)*cumo_half2float(x))
66
+ #define m_floor(x) cumo_float2half(floorf(cumo_half2float(x)))
67
+ #define m_round(x) cumo_float2half(roundf(cumo_half2float(x)))
68
+ #define m_ceil(x) cumo_float2half(ceilf(cumo_half2float(x)))
69
+ #define m_trunc(x) cumo_float2half(truncf(cumo_half2float(x)))
70
+ #define m_rint(x) cumo_float2half(rintf(cumo_half2float(x)))
71
+ #define m_sign(x) cumo_float2half(cumo_half_sign(cumo_half2float(x)))
72
+ #define m_copysign(x,y) cumo_float2half(copysignf(cumo_half2float(x),cumo_half2float(y)))
73
+ #define m_signbit(x) signbit(cumo_half2float(x))
74
+ #define m_modf(x,y,z) {float cumo_h_i; float cumo_h_f = modff(cumo_half2float(x),&cumo_h_i); y = cumo_float2half(cumo_h_f); z = cumo_float2half(cumo_h_i);}
75
+
76
+ #define m_eq(x,y) (cumo_half2float(x)==cumo_half2float(y))
77
+ #define m_ne(x,y) (cumo_half2float(x)!=cumo_half2float(y))
78
+ #define m_gt(x,y) (cumo_half2float(x)>cumo_half2float(y))
79
+ #define m_ge(x,y) (cumo_half2float(x)>=cumo_half2float(y))
80
+ #define m_lt(x,y) (cumo_half2float(x)<cumo_half2float(y))
81
+ #define m_le(x,y) (cumo_half2float(x)<=cumo_half2float(y))
82
+
83
+ #define m_isnan(x) isnan(cumo_half2float(x))
84
+ #define m_isinf(x) isinf(cumo_half2float(x))
85
+ #define m_isposinf(x) (isinf(cumo_half2float(x)) && signbit(cumo_half2float(x))==0)
86
+ #define m_isneginf(x) (isinf(cumo_half2float(x)) && signbit(cumo_half2float(x)))
87
+ #define m_isfinite(x) isfinite(cumo_half2float(x))
88
+
89
+ #define not_nan(x) cumo_half_not_nan(x)
90
+
91
+ #define m_mulsum_init m_zero
92
+
93
+ #define m_sprintf(s,x) sprintf(s,"%g",cumo_half2float(x))
94
+
95
+ #define m_sqrt(x) cumo_float2half(sqrtf(cumo_half2float(x)))
96
+ #define m_cbrt(x) cumo_float2half(cbrtf(cumo_half2float(x)))
97
+ #define m_log(x) cumo_float2half(logf(cumo_half2float(x)))
98
+ #define m_log2(x) cumo_float2half(log2f(cumo_half2float(x)))
99
+ #define m_log10(x) cumo_float2half(log10f(cumo_half2float(x)))
100
+ #define m_exp(x) cumo_float2half(expf(cumo_half2float(x)))
101
+ #define m_exp2(x) cumo_float2half(exp2f(cumo_half2float(x)))
102
+ #ifdef HAVE_EXP10
103
+ #define m_exp10(x) cumo_float2half(exp10f(cumo_half2float(x)))
104
+ #else
105
+ #define m_exp10(x) cumo_float2half(powf(10.0f,cumo_half2float(x)))
106
+ #endif
107
+ #define m_expm1(x) cumo_float2half(expm1f(cumo_half2float(x)))
108
+ #define m_log1p(x) cumo_float2half(log1pf(cumo_half2float(x)))
109
+
110
+ #define m_sin(x) cumo_float2half(sinf(cumo_half2float(x)))
111
+ #define m_cos(x) cumo_float2half(cosf(cumo_half2float(x)))
112
+ #define m_tan(x) cumo_float2half(tanf(cumo_half2float(x)))
113
+ #define m_asin(x) cumo_float2half(asinf(cumo_half2float(x)))
114
+ #define m_acos(x) cumo_float2half(acosf(cumo_half2float(x)))
115
+ #define m_atan(x) cumo_float2half(atanf(cumo_half2float(x)))
116
+ #define m_sinh(x) cumo_float2half(sinhf(cumo_half2float(x)))
117
+ #define m_cosh(x) cumo_float2half(coshf(cumo_half2float(x)))
118
+ #define m_tanh(x) cumo_float2half(tanhf(cumo_half2float(x)))
119
+ #define m_asinh(x) cumo_float2half(asinhf(cumo_half2float(x)))
120
+ #define m_acosh(x) cumo_float2half(acoshf(cumo_half2float(x)))
121
+ #define m_atanh(x) cumo_float2half(atanhf(cumo_half2float(x)))
122
+ #define m_atan2(x,y) cumo_float2half(atan2f(cumo_half2float(x),cumo_half2float(y)))
123
+ #define m_hypot(x,y) cumo_float2half(hypotf(cumo_half2float(x),cumo_half2float(y)))
124
+ #define m_sinc(x) cumo_float2half(cumo_half_sinc(cumo_half2float(x)))
125
+
126
+ #define m_erf(x) cumo_float2half(erff(cumo_half2float(x)))
127
+ #define m_erfc(x) cumo_float2half(erfcf(cumo_half2float(x)))
128
+ #define m_ldexp(x,y) cumo_float2half(cumo_half_ldexp(cumo_half2float(x),cumo_half2float(y)))
129
+ #define m_frexp(x,exp) cumo_float2half(frexpf(cumo_half2float(x),exp))
130
+
131
+
132
+ __host__ __device__ static inline float cumo_half_pow_positive_int(float x, unsigned int p)
133
+ {
134
+ float r = 1.0f;
135
+ switch (p) {
136
+ case 0: return 1.0f;
137
+ case 1: return x;
138
+ case 2: return x*x;
139
+ case 3: return x*x*x;
140
+ case 4: x = x*x; return x*x;
141
+ }
142
+ if (p > 64) return powf(x, (float)p);
143
+ while (p) {
144
+ if (p & 1) r *= x;
145
+ x *= x;
146
+ p >>= 1;
147
+ }
148
+ return r;
149
+ }
150
+
151
+ __host__ __device__ static inline float cumo_half_pow_int(float x, int p)
152
+ {
153
+ if (p < 0) return 1.0f / cumo_half_pow_positive_int(x, -(unsigned int)p);
154
+ return cumo_half_pow_positive_int(x, (unsigned int)p);
155
+ }
156
+
157
+ // The bit-pattern intrinsics are device-only before CUDA 12, so the bits are
158
+ // taken the way a host caller can take them too.
159
+ __host__ __device__ static inline cumo_half cumo_half_step_down(cumo_half h)
160
+ {
161
+ unsigned short b;
162
+ cumo_half r;
163
+ memcpy(&b, &h, sizeof(b));
164
+ if (b == 0x0000u) {
165
+ b = 0x8001u;
166
+ } else {
167
+ b = (unsigned short)((b & 0x8000u) ? (b + 1) : (b - 1));
168
+ }
169
+ memcpy(&r, &b, sizeof(b));
170
+ return r;
171
+ }
172
+
173
+ __host__ __device__ static inline float cumo_half_ldexp(float x, float y)
174
+ {
175
+ if (!(y == y)) return y;
176
+ if (y > 64.0f) y = 64.0f;
177
+ if (y < -64.0f) y = -64.0f;
178
+ return ldexpf(x, (int)y);
179
+ }
180
+
181
+ __host__ __device__ static inline float cumo_half_sinc(float x)
182
+ {
183
+ return (x==0) ? 1.0f : (sinf(x)/x);
184
+ }
185
+
186
+ __host__ __device__ static inline float cumo_half_sign(float x)
187
+ {
188
+ return (x==0) ? 0.0f : ((x>0) ? 1.0f : ((x<0) ? -1.0f : x));
189
+ }
190
+
191
+ __host__ __device__ static inline cumo_half f_seq(cumo_half x, cumo_half y, double c)
192
+ {
193
+ return cumo_float2half(cumo_half2float(x) + cumo_half2float(y) * (float)c);
194
+ }
195
+
196
+ #include "real_accum_kernel.h"
197
+
198
+ #endif // CUMO_HALF_MACRO_KERNEL_H
@@ -0,0 +1,22 @@
1
+ #include "half_def.h"
2
+
3
+ typedef cumo_half dtype;
4
+ typedef cumo_half rtype;
5
+ #define cT cumo_cHFloat
6
+ #define cRT cumo_cHFloat
7
+ #define mTM cumo_mHFloatMath
8
+
9
+ #include "half_macro.h"
10
+ #include "cublas_v2.h"
11
+ #include "cumo/cuda/cublas.h"
12
+ #include "cumo/cuda/cudnn.h"
13
+
14
+ #define m_extract(x) rb_float_new(cumo_half2float(*(cumo_half*)x))
15
+ #define m_nearly_eq(x,y) (fabsf(cumo_half2float(x)-cumo_half2float(y))<=(fabsf(cumo_half2float(x))+fabsf(cumo_half2float(y)))*CUMO_HALF_EPSILON*2)
16
+
17
+ #define M_EPSILON rb_float_new(9.765625e-04)
18
+ #define M_MIN rb_float_new(6.103515625e-05)
19
+ #define M_MAX rb_float_new(65504.0)
20
+
21
+ #define DATA_MIN cumo_float2half(-65504.0f)
22
+ #define DATA_MAX cumo_float2half(65504.0f)
@@ -0,0 +1,16 @@
1
+ #ifndef CUMO_HFLOAT_KERNEL_H
2
+ #define CUMO_HFLOAT_KERNEL_H
3
+
4
+ #include "half_def_kernel.h"
5
+
6
+ typedef cumo_half dtype;
7
+ typedef cumo_half rtype;
8
+
9
+ #include "half_macro_kernel.h"
10
+
11
+ #define m_nearly_eq(x,y) (fabsf(cumo_half2float(x)-cumo_half2float(y))<=(fabsf(cumo_half2float(x))+fabsf(cumo_half2float(y)))*CUMO_HALF_EPSILON*2)
12
+
13
+ #define DATA_MIN cumo_float2half(-65504.0f)
14
+ #define DATA_MAX cumo_float2half(65504.0f)
15
+
16
+ #endif // CUMO_HFLOAT_KERNEL_H
@@ -1,4 +1,6 @@
1
+ #ifndef not_nan
1
2
  #define not_nan(x) ((x)==(x))
3
+ #endif
2
4
 
3
5
  #define m_mulsum(x,y,z) {z = m_add(m_mul(x,y),z);}
4
6
  #define m_mulsum_nan(x,y,z) { \
@@ -1,7 +1,9 @@
1
1
  #ifndef CUMO_REAL_ACCUM_KERNEL_H
2
2
  #define CUMO_REAL_ACCUM_KERNEL_H
3
3
 
4
+ #ifndef not_nan
4
5
  #define not_nan(x) ((x)==(x))
6
+ #endif
5
7
 
6
8
  #define m_mulsum(x,y,z) {z = m_add(m_mul(x,y),z);}
7
9
  #define m_mulsum_nan(x,y,z) { \
@@ -1,3 +1,5 @@
1
+ #include "half_def.h"
2
+
1
3
  #define m_zero INT2FIX(0)
2
4
  #define m_one INT2FIX(1)
3
5
 
@@ -6,6 +8,7 @@
6
8
 
7
9
  #define m_from_double(x) rb_float_new(x)
8
10
  #define m_from_real(x) rb_float_new(x)
11
+ #define m_from_half(x) m_from_real(cumo_half2float(x))
9
12
  #define m_from_sint(x) INT2FIX(x)
10
13
  #define m_from_int32(x) INT322NUM(x)
11
14
  #define m_from_int64(x) INT642NUM(x)
@@ -1,3 +1,5 @@
1
+ #include "half_def.h"
2
+
1
3
  #define m_zero 0
2
4
  #define m_one 1
3
5
 
@@ -6,6 +8,7 @@
6
8
  /* Handle negative values consistently across platforms for unsigned integer types */
7
9
  #define m_from_double(x) ((x) < 0 ? (dtype)((long long)(x)) : (dtype)(x))
8
10
  #define m_from_real(x) ((x) < 0 ? (dtype)((long long)(x)) : (dtype)(x))
11
+ #define m_from_half(x) m_from_real(cumo_half2float(x))
9
12
  #define m_from_sint(x) (x)
10
13
  #define m_from_int32(x) (x)
11
14
  #define m_from_int64(x) (x)
@@ -1,11 +1,13 @@
1
1
  #ifndef CUMO_XINT_MACRO_KERNEL_H
2
2
  #define CUMO_XINT_MACRO_KERNEL_H
3
+ #include "half_def_kernel.h"
3
4
 
4
5
  #define m_zero 0
5
6
  #define m_one 1
6
7
 
7
8
  #define m_from_double(x) (x)
8
9
  #define m_from_real(x) (x)
10
+ #define m_from_half(x) m_from_real(cumo_half2float(x))
9
11
  #define m_from_sint(x) (x)
10
12
  #define m_from_int32(x) (x)
11
13
  #define m_from_int64(x) (x)
@@ -10,8 +10,8 @@ extern "C" {
10
10
  #endif
11
11
  #endif
12
12
 
13
- #define CUMO_VERSION "0.6.0"
14
- #define CUMO_VERSION_CODE 600
13
+ #define CUMO_VERSION "0.7.0"
14
+ #define CUMO_VERSION_CODE 700
15
15
 
16
16
  bool cumo_compatible_mode_enabled_p();
17
17
  bool cumo_show_warning_enabled_p();
@@ -77,7 +77,7 @@ iter_copy_bytes(cumo_na_loop_t *const lp)
77
77
  // with nothing ordering that against the host reading it back.
78
78
  if (idx1 || idx2) {
79
79
  CUMO_SHOW_SYNCHRONIZE_WARNING_ONCE("copy", "any");
80
- cumo_cuda_runtime_check_status(cudaDeviceSynchronize());
80
+ cumo_cuda_runtime_device_synchronize();
81
81
  }
82
82
  e = lp->args[0].elmsz;
83
83
  LOOP_UNARY_PTR(lp,m_memcpy);
@@ -256,6 +256,8 @@ cumo_na_swapaxes(VALUE self, VALUE a1, VALUE a2)
256
256
  cumo_narray_view_t *na;
257
257
  volatile VALUE view;
258
258
 
259
+ // cumo_na_make_view borrows, so index_owned is zero and the swap below
260
+ // has no ownership bits to carry with the strides.
259
261
  view = cumo_na_make_view(self);
260
262
  CumoGetNArrayView(view,na);
261
263
 
@@ -459,6 +461,8 @@ cumo_na_reshape_bang(int argc, VALUE *argv, VALUE self)
459
461
  if (OBJ_FROZEN(self)) {
460
462
  rb_raise(rb_eRuntimeError, "cannot write to frozen NArray.");
461
463
  }
464
+ // A contiguous view has every dimension on a stride, so overwriting them
465
+ // below drops no index array this view owns.
462
466
  if (cumo_na_check_contiguous(self)==Qfalse) {
463
467
  rb_raise(rb_eStandardError, "cannot change shape of non-contiguous NArray");
464
468
  }
@@ -469,15 +473,15 @@ cumo_na_reshape_bang(int argc, VALUE *argv, VALUE self)
469
473
  if (na->type == CUMO_NARRAY_VIEW_T) {
470
474
  CumoGetNArrayView(self, na2);
471
475
  if (na->ndim < argc) {
472
- stridx = ALLOC_N(cumo_stridx_t,argc);
476
+ stridx = ZALLOC_N(cumo_stridx_t,argc);
473
477
  } else {
474
478
  stridx = na2->stridx;
475
479
  }
476
- if (na->ndim == 0) {
477
- stride = cumo_na_element_stride(self);
478
- } else {
479
- stride = CUMO_SDX_GET_STRIDE(na2->stridx[na->ndim-1]);
480
- }
480
+ // A contiguous view holds its elements one after another from its
481
+ // offset, so the step between them is the element size whatever the
482
+ // strides say: a length-1 dimension may carry any stride, including a
483
+ // negative one.
484
+ stride = cumo_na_element_stride(self);
481
485
  for (i=argc; i--;) {
482
486
  CUMO_SDX_SET_STRIDE(stridx[i],stride);
483
487
  stride *= shape[i];
@@ -526,11 +530,11 @@ VALUE
526
530
  cumo_na_flatten_dim(VALUE self, int sd)
527
531
  {
528
532
  int i, nd, fd;
529
- size_t *idx1, *idx2;
533
+ size_t *idx2;
530
534
  size_t stride;
531
535
  size_t *shape, size;
532
536
  cumo_narray_t *na;
533
- cumo_narray_view_t *na1, *na2;
537
+ cumo_narray_view_t *na1 = NULL, *na2;
534
538
  volatile VALUE view;
535
539
 
536
540
  CumoGetNArray(self,na);
@@ -561,7 +565,7 @@ cumo_na_flatten_dim(VALUE self, int sd)
561
565
 
562
566
  // new stride
563
567
  cumo_na_setup_shape((cumo_narray_t*)na2, sd+1, shape);
564
- na2->stridx = ALLOC_N(cumo_stridx_t,sd+1);
568
+ na2->stridx = ZALLOC_N(cumo_stridx_t,sd+1);
565
569
 
566
570
  switch(na->type) {
567
571
  case CUMO_NARRAY_DATA_T:
@@ -578,25 +582,29 @@ cumo_na_flatten_dim(VALUE self, int sd)
578
582
  CumoGetNArrayView(self, na1);
579
583
  na2->data = na1->data;
580
584
  na2->offset = na1->offset;
585
+ // Every caller passes sd == 0 today, so this loop does not run.
581
586
  for (i=0; i<sd; i++) {
587
+ na2->stridx[i] = na1->stridx[i];
582
588
  if (CUMO_SDX_IS_INDEX(na1->stridx[i])) {
583
- idx1 = CUMO_SDX_GET_INDEX(na1->stridx[i]);
584
- idx2 = (size_t*)cumo_cuda_runtime_malloc(sizeof(size_t)*shape[i]);
585
- cumo_cuda_runtime_check_status(cudaMemcpyAsync(idx2,idx1,sizeof(size_t)*shape[i],cudaMemcpyDeviceToDevice,0));
586
- CUMO_SDX_SET_INDEX(na2->stridx[i],idx2);
587
- } else {
588
- na2->stridx[i] = na1->stridx[i];
589
+ cumo_na_index_borrow(na2, self);
589
590
  }
590
591
  }
591
- // flat dimenion == last dimension
592
+ // flat dimension == last dimension that advances. A length-1 dimension
593
+ // is not part of the chain cumo_na_check_ladder() walks, so the stride
594
+ // at nd-1 may be any value.
592
595
  if (RTEST(cumo_na_check_ladder(self,sd))) {
593
- na2->stridx[sd] = na1->stridx[nd-1];
596
+ i = cumo_na_last_dim_with_elements(na, sd);
597
+ if (i < 0) {
598
+ CUMO_SDX_SET_STRIDE(na2->stridx[sd], (ssize_t)cumo_na_element_stride(self));
599
+ } else {
600
+ na2->stridx[sd] = na1->stridx[i];
601
+ }
594
602
  } else {
595
603
  cumo_na_iarray_stridx_t iarray;
596
604
  cumo_na_indexer_t indexer;
597
605
 
598
606
  idx2 = (size_t*)cumo_cuda_runtime_malloc(sizeof(size_t)*((shape[sd]==0) ? 1 : shape[sd]));
599
- CUMO_SDX_SET_INDEX(na2->stridx[sd],idx2);
607
+ cumo_na_index_own(na2,sd,idx2);
600
608
  fd = nd-sd;
601
609
  iarray.ptr = NULL;
602
610
  indexer.ndim = fd;
@@ -609,7 +617,11 @@ cumo_na_flatten_dim(VALUE self, int sd)
609
617
  }
610
618
  break;
611
619
  }
612
- cumo_na_index_mark_filled(na2);
620
+ if (na1 != NULL) {
621
+ cumo_na_index_mark_derived(na2, na1);
622
+ } else {
623
+ cumo_na_index_mark_filled(na2);
624
+ }
613
625
  return view;
614
626
  }
615
627
 
@@ -667,13 +679,13 @@ void cumo_na_diagonal_stride_index_kernel_launch(size_t *idx, ssize_t s0, size_t
667
679
  static VALUE
668
680
  cumo_na_diagonal(int argc, VALUE *argv, VALUE self)
669
681
  {
670
- int i, k, nd;
682
+ int i, k, nd, borrow;
671
683
  size_t *idx0, *idx1, *diag_idx;
672
684
  size_t *shape;
673
685
  size_t diag_size;
674
686
  ssize_t stride, stride0, stride1;
675
687
  cumo_narray_t *na;
676
- cumo_narray_view_t *na1, *na2;
688
+ cumo_narray_view_t *na1 = NULL, *na2;
677
689
  VALUE view;
678
690
  VALUE vofs=0, vaxes=0;
679
691
  ssize_t kofs;
@@ -768,7 +780,7 @@ cumo_na_diagonal(int argc, VALUE *argv, VALUE self)
768
780
 
769
781
  // new stride
770
782
  cumo_na_setup_shape((cumo_narray_t*)na2, nd-1, shape);
771
- na2->stridx = ALLOC_N(cumo_stridx_t, nd-1);
783
+ na2->stridx = ZALLOC_N(cumo_stridx_t, nd-1);
772
784
 
773
785
  switch(na->type) {
774
786
  case CUMO_NARRAY_DATA_T:
@@ -799,19 +811,19 @@ cumo_na_diagonal(int argc, VALUE *argv, VALUE self)
799
811
  CumoGetNArrayView(self, na1);
800
812
  na2->data = na1->data;
801
813
  na2->offset = na1->offset;
814
+ borrow = !CUMO_SDX_IS_INDEX(na1->stridx[ax[0]]) && !CUMO_SDX_IS_INDEX(na1->stridx[ax[1]]);
802
815
  for (i=k=0; i<nd; i++) {
803
816
  if (i != ax[0] && i != ax[1]) {
804
- if (CUMO_SDX_IS_INDEX(na1->stridx[i])) {
817
+ if (borrow || !CUMO_SDX_IS_INDEX(na1->stridx[i])) {
818
+ na2->stridx[k] = na1->stridx[i];
819
+ if (CUMO_SDX_IS_INDEX(na1->stridx[i])) {
820
+ cumo_na_index_borrow(na2, self);
821
+ }
822
+ } else {
805
823
  idx0 = CUMO_SDX_GET_INDEX(na1->stridx[i]);
806
- // idx1 = ALLOC_N(size_t, na->shape[i]);
807
- // for (j=0; j<na->shape[i]; j++) {
808
- // idx1[j] = idx0[j];
809
- // }
810
824
  idx1 = (size_t*)cumo_cuda_runtime_malloc(sizeof(size_t)*na->shape[i]);
825
+ cumo_na_index_own(na2,k,idx1);
811
826
  cumo_cuda_runtime_check_status(cudaMemcpyAsync(idx1,idx0,sizeof(size_t)*na->shape[i],cudaMemcpyDeviceToDevice,0));
812
- CUMO_SDX_SET_INDEX(na2->stridx[k],idx1);
813
- } else {
814
- na2->stridx[k] = na1->stridx[i];
815
827
  }
816
828
  k++;
817
829
  }
@@ -820,6 +832,7 @@ cumo_na_diagonal(int argc, VALUE *argv, VALUE self)
820
832
  idx0 = CUMO_SDX_GET_INDEX(na1->stridx[ax[0]]);
821
833
  // diag_idx = ALLOC_N(size_t, diag_size);
822
834
  diag_idx = (size_t*)cumo_cuda_runtime_malloc(sizeof(size_t)*diag_size);
835
+ cumo_na_index_own(na2,nd-2,diag_idx);
823
836
  if (CUMO_SDX_IS_INDEX(na1->stridx[ax[1]])) {
824
837
  idx1 = CUMO_SDX_GET_INDEX(na1->stridx[ax[1]]);
825
838
  cumo_na_diagonal_index_index_kernel_launch(diag_idx, idx0, idx1, k0, k1, diag_size);
@@ -827,15 +840,14 @@ cumo_na_diagonal(int argc, VALUE *argv, VALUE self)
827
840
  stride1 = CUMO_SDX_GET_STRIDE(na1->stridx[ax[1]]);
828
841
  cumo_na_diagonal_index_stride_kernel_launch(diag_idx, idx0, stride1, k0, k1, diag_size);
829
842
  }
830
- CUMO_SDX_SET_INDEX(na2->stridx[nd-2],diag_idx);
831
843
  } else {
832
844
  stride0 = CUMO_SDX_GET_STRIDE(na1->stridx[ax[0]]);
833
845
  if (CUMO_SDX_IS_INDEX(na1->stridx[ax[1]])) {
834
846
  idx1 = CUMO_SDX_GET_INDEX(na1->stridx[ax[1]]);
835
847
  // diag_idx = ALLOC_N(size_t, diag_size);
836
848
  diag_idx = (size_t*)cumo_cuda_runtime_malloc(sizeof(size_t)*diag_size);
849
+ cumo_na_index_own(na2,nd-2,diag_idx);
837
850
  cumo_na_diagonal_stride_index_kernel_launch(diag_idx, stride0, idx1, k0, k1, diag_size);
838
- CUMO_SDX_SET_INDEX(na2->stridx[nd-2],diag_idx);
839
851
  } else {
840
852
  stride1 = CUMO_SDX_GET_STRIDE(na1->stridx[ax[1]]);
841
853
  na2->offset += stride0*k0 + stride1*k1;
@@ -844,153 +856,17 @@ cumo_na_diagonal(int argc, VALUE *argv, VALUE self)
844
856
  }
845
857
  break;
846
858
  }
847
- return view;
848
- }
849
-
850
- //----------------------------------------------------------------------
851
-
852
-
853
- #if 0
854
- #ifdef SWAP
855
- #undef SWAP
856
- #endif
857
- #define SWAP(a,b,t) {t=a;a=b;b=t;}
858
-
859
- static VALUE
860
- cumo_na_new_dimension_for_dot(VALUE self, int pos, int len, bool transpose)
861
- {
862
- int i, k, l, nd;
863
- size_t j;
864
- size_t *idx1, *idx2;
865
- size_t *shape;
866
- ssize_t stride;
867
- cumo_narray_t *na;
868
- cumo_narray_view_t *na1, *na2;
869
- size_t shape_n;
870
- cumo_stridx_t stridx_n;
871
- volatile VALUE view;
872
-
873
- CumoGetNArray(self,na);
874
- nd = na->ndim;
875
-
876
- view = cumo_na_s_allocate_view(rb_obj_class(self));
877
-
878
- cumo_na_copy_flags(self, view);
879
- CumoGetNArrayView(view, na2);
880
-
881
- // new dimension
882
- if (pos < 0) pos += nd;
883
- if (pos > nd || pos < 0) {
884
- rb_raise(rb_eRangeError,"new dimension is out of range");
885
- }
886
- nd += len;
887
- shape = ALLOCA_N(size_t,nd);
888
- na2->stridx = ALLOC_N(cumo_stridx_t,nd);
889
-
890
- switch(na->type) {
891
- case CUMO_NARRAY_DATA_T:
892
- case CUMO_NARRAY_FILEMAP_T:
893
- i = k = 0;
894
- while (i < nd) {
895
- if (i == pos && len > 0) {
896
- for (l=0; l<len; l++) {
897
- shape[i++] = 1;
898
- }
899
- } else {
900
- shape[i++] = na->shape[k++];
901
- }
902
- }
903
- cumo_na_setup_shape((cumo_narray_t*)na2, nd, shape);
904
- stride = cumo_na_element_stride(self);
905
- for (i=nd; i--;) {
906
- CUMO_SDX_SET_STRIDE(na2->stridx[i], stride);
907
- stride *= shape[i];
908
- }
909
- na2->offset = 0;
910
- na2->data = self;
911
- break;
912
- case CUMO_NARRAY_VIEW_T:
913
- CumoGetNArrayView(self, na1);
914
- i = k = 0;
915
- while (i < nd) {
916
- if (i == pos && len > 0) {
917
- if (CUMO_SDX_IS_INDEX(na1->stridx[k])) {
918
- stride = CUMO_SDX_GET_INDEX(na1->stridx[k])[0];
919
- } else {
920
- stride = CUMO_SDX_GET_STRIDE(na1->stridx[k]);
921
- }
922
- for (l=0; l<len; l++) {
923
- shape[i] = 1;
924
- CUMO_SDX_SET_STRIDE(na2->stridx[i], stride);
925
- i++;
926
- }
927
- } else {
928
- shape[i] = na1->base.shape[k];
929
- if (CUMO_SDX_IS_INDEX(na1->stridx[k])) {
930
- idx1 = CUMO_SDX_GET_INDEX(na1->stridx[k]);
931
- idx2 = ALLOC_N(size_t,na1->base.shape[k]);
932
- for (j=0; j<na1->base.shape[k]; j++) {
933
- idx2[j] = idx1[j];
934
- }
935
- CUMO_SDX_SET_INDEX(na2->stridx[i], idx2);
936
- } else {
937
- na2->stridx[i] = na1->stridx[k];
938
- }
939
- i++; k++;
940
- }
941
- }
942
- cumo_na_setup_shape((cumo_narray_t*)na2, nd, shape);
943
- na2->offset = na1->offset;
944
- na2->data = na1->data;
945
- break;
946
- }
947
-
948
- if (transpose) {
949
- SWAP(na2->base.shape[nd-1], na2->base.shape[nd-2], shape_n);
950
- SWAP(na2->stridx[nd-1], na2->stridx[nd-2], stridx_n);
859
+ if (na1 != NULL) {
860
+ cumo_na_index_mark_derived(na2, na1);
861
+ } else {
862
+ cumo_na_index_mark_filled(na2);
951
863
  }
952
-
953
864
  return view;
954
865
  }
955
866
 
956
-
957
867
  //----------------------------------------------------------------------
958
868
 
959
- /*
960
- * call-seq:
961
- * narray.dot(other) => narray
962
- *
963
- * Returns dot product.
964
- *
965
- */
966
-
967
- static VALUE
968
- cumo_na_dot(VALUE self, VALUE other)
969
- {
970
- volatile VALUE a1=self, a2=other;
971
- cumo_narray_t *na1, *na2;
972
869
 
973
- if (!rb_respond_to(a1, cumo_id_mulsum)) {
974
- rb_raise(rb_eNoMethodError,"requires mulsum method for dot method");
975
- }
976
- CumoGetNArray(a1,na1);
977
- CumoGetNArray(a2,na2);
978
- if (na1->ndim==0 || na2->ndim==0) {
979
- rb_raise(cumo_na_eDimensionError,"zero dimensional narray");
980
- }
981
- if (na2->ndim > 1) {
982
- if (na1->shape[na1->ndim-1] != na2->shape[na2->ndim-2]) {
983
- rb_raise(cumo_na_eShapeError,"shape mismatch: self.shape[-1](=%"SZF"d) != other.shape[-2](=%"SZF"d)",
984
- na1->shape[na1->ndim-1], na2->shape[na2->ndim-2]);
985
- }
986
- // insert new axis [ ..., last-1-dim, newaxis*other.ndim, last-dim ]
987
- a1 = cumo_na_new_dimension_for_dot(a1, na1->ndim-1, na2->ndim-1, 0);
988
- // insert & transpose [ newaxis*self.ndim, ..., last-dim, last-1-dim ]
989
- a2 = cumo_na_new_dimension_for_dot(a2, 0, na1->ndim-1, 1);
990
- }
991
- return rb_funcall(a1,cumo_id_mulsum,2,a2,INT2FIX(-1));
992
- }
993
- #endif
994
870
 
995
871
  void
996
872
  Init_cumo_na_data(void)
@@ -1024,7 +900,6 @@ Init_cumo_na_data(void)
1024
900
  rb_define_method(cNArray, "to_host", cumo_na_to_host, 0);
1025
901
  rb_define_method(cNArray, "to_swapped", cumo_na_to_swapped, 0);
1026
902
 
1027
- //rb_define_method(cNArray, "dot", cumo_na_dot, 1);
1028
903
 
1029
904
  cumo_id_copy = rb_intern("copy");
1030
905
  cumo_id_mulsum = rb_intern("mulsum");