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
|
@@ -62,6 +62,102 @@
|
|
|
62
62
|
// limit of 2^31-1 is far above this.
|
|
63
63
|
#define CUMO_MAX_GRID_DIM (4294967295ul / CUMO_MAX_BLOCK_DIM)
|
|
64
64
|
|
|
65
|
+
// A transpose has one side strided whichever way it is walked, so it stages a
|
|
66
|
+
// square tile in shared memory and reads and writes both sides in rows. The
|
|
67
|
+
// extra column spreads a tile's rows over the banks: for a 4-byte element that
|
|
68
|
+
// leaves no conflict at all, and it drops an 8-byte one to 2-way and a 16-byte
|
|
69
|
+
// one to 4-way. TILE must stay a multiple of ROWS.
|
|
70
|
+
#define CUMO_TRANSPOSE_TILE 32
|
|
71
|
+
#define CUMO_TRANSPOSE_ROWS 8
|
|
72
|
+
|
|
73
|
+
// gridDim.y and gridDim.z stop at 65535, unlike gridDim.x.
|
|
74
|
+
#define CUMO_MAX_GRID_DIM_Y 65535
|
|
75
|
+
|
|
76
|
+
// The tile a CUMO_TRANSPOSE_TILE_LOOP stages through. The extra column is what
|
|
77
|
+
// spreads its rows over the banks, so the loop reads it back along either axis
|
|
78
|
+
// without conflicting with itself.
|
|
79
|
+
#define CUMO_TRANSPOSE_TILE_DECL(type, name) \
|
|
80
|
+
__shared__ type name[CUMO_TRANSPOSE_TILE][CUMO_TRANSPOSE_TILE + 1]
|
|
81
|
+
|
|
82
|
+
// Tiles only pay off once both sides reach one. A shorter side leaves most of
|
|
83
|
+
// each warp idle, while the plain loop already reads or writes it in one go.
|
|
84
|
+
#define CUMO_TRANSPOSE_TILE_FITS(indexer) \
|
|
85
|
+
((indexer)->ndim == 2 && \
|
|
86
|
+
(indexer)->shape[0] >= CUMO_TRANSPOSE_TILE && \
|
|
87
|
+
(indexer)->shape[1] >= CUMO_TRANSPOSE_TILE)
|
|
88
|
+
|
|
89
|
+
// Walks a rows-by-cols transpose one tile at a time.
|
|
90
|
+
//
|
|
91
|
+
// STAGE reads one element of the transposed side, which sits at cumo_tile_src
|
|
92
|
+
// of that side's own layout, and lands in cumo_tile_val. The body then runs
|
|
93
|
+
// once per output element, at cumo_tile_dst of the row-major layout the output
|
|
94
|
+
// and any other operand share.
|
|
95
|
+
//
|
|
96
|
+
// The body runs inside two nested loops, after a __syncthreads(). A continue
|
|
97
|
+
// there skips one output element, a break leaves the current tile but not the
|
|
98
|
+
// walk, and a return deadlocks the block on the next __syncthreads().
|
|
99
|
+
#define CUMO_TRANSPOSE_TILE_LOOP(tile, rows, cols, STAGE, ...) \
|
|
100
|
+
do { \
|
|
101
|
+
uint64_t cumo_tile_rows = (rows); \
|
|
102
|
+
uint64_t cumo_tile_cols = (cols); \
|
|
103
|
+
uint64_t cumo_tile_base; \
|
|
104
|
+
\
|
|
105
|
+
for (cumo_tile_base = (uint64_t)blockIdx.y * CUMO_TRANSPOSE_TILE; \
|
|
106
|
+
cumo_tile_base < cumo_tile_rows; \
|
|
107
|
+
cumo_tile_base += (uint64_t)gridDim.y * CUMO_TRANSPOSE_TILE) { \
|
|
108
|
+
uint64_t cumo_tile_x = cumo_tile_base + threadIdx.x; \
|
|
109
|
+
uint64_t cumo_tile_y = \
|
|
110
|
+
(uint64_t)blockIdx.x * CUMO_TRANSPOSE_TILE + threadIdx.y; \
|
|
111
|
+
int cumo_tile_j; \
|
|
112
|
+
\
|
|
113
|
+
__syncthreads(); \
|
|
114
|
+
for (cumo_tile_j = 0; \
|
|
115
|
+
threadIdx.y + cumo_tile_j < CUMO_TRANSPOSE_TILE; \
|
|
116
|
+
cumo_tile_j += CUMO_TRANSPOSE_ROWS) { \
|
|
117
|
+
if (cumo_tile_x < cumo_tile_rows && \
|
|
118
|
+
cumo_tile_y + cumo_tile_j < cumo_tile_cols) { \
|
|
119
|
+
uint64_t cumo_tile_src = \
|
|
120
|
+
(cumo_tile_y + cumo_tile_j) * cumo_tile_rows + cumo_tile_x; \
|
|
121
|
+
(tile)[threadIdx.y + cumo_tile_j][threadIdx.x] = STAGE; \
|
|
122
|
+
} \
|
|
123
|
+
} \
|
|
124
|
+
__syncthreads(); \
|
|
125
|
+
cumo_tile_x = (uint64_t)blockIdx.x * CUMO_TRANSPOSE_TILE + threadIdx.x; \
|
|
126
|
+
cumo_tile_y = cumo_tile_base + threadIdx.y; \
|
|
127
|
+
for (cumo_tile_j = 0; \
|
|
128
|
+
threadIdx.y + cumo_tile_j < CUMO_TRANSPOSE_TILE; \
|
|
129
|
+
cumo_tile_j += CUMO_TRANSPOSE_ROWS) { \
|
|
130
|
+
if (cumo_tile_x < cumo_tile_cols && \
|
|
131
|
+
cumo_tile_y + cumo_tile_j < cumo_tile_rows) { \
|
|
132
|
+
uint64_t cumo_tile_dst = \
|
|
133
|
+
(cumo_tile_y + cumo_tile_j) * cumo_tile_cols + cumo_tile_x; \
|
|
134
|
+
auto cumo_tile_val = \
|
|
135
|
+
(tile)[threadIdx.x][threadIdx.y + cumo_tile_j]; \
|
|
136
|
+
__VA_ARGS__ \
|
|
137
|
+
} \
|
|
138
|
+
} \
|
|
139
|
+
} \
|
|
140
|
+
} while (0)
|
|
141
|
+
|
|
142
|
+
// Launches such a kernel, which takes its own arguments and then rows and cols.
|
|
143
|
+
// gridDim.y walks tile rows on its own, but gridDim.x has to cover every tile
|
|
144
|
+
// column: a short grid there drops the columns past it without an error.
|
|
145
|
+
#define CUMO_TRANSPOSE_LAUNCH(kernel, rows, cols, ...) \
|
|
146
|
+
do { \
|
|
147
|
+
uint64_t cumo_launch_rows = (rows); \
|
|
148
|
+
uint64_t cumo_launch_cols = (cols); \
|
|
149
|
+
uint64_t cumo_launch_tiles_y = \
|
|
150
|
+
(cumo_launch_rows + CUMO_TRANSPOSE_TILE - 1) / CUMO_TRANSPOSE_TILE; \
|
|
151
|
+
dim3 cumo_launch_grid( \
|
|
152
|
+
(unsigned int)((cumo_launch_cols + CUMO_TRANSPOSE_TILE - 1) / CUMO_TRANSPOSE_TILE), \
|
|
153
|
+
(unsigned int)(cumo_launch_tiles_y > CUMO_MAX_GRID_DIM_Y \
|
|
154
|
+
? CUMO_MAX_GRID_DIM_Y : cumo_launch_tiles_y)); \
|
|
155
|
+
dim3 cumo_launch_block(CUMO_TRANSPOSE_TILE, CUMO_TRANSPOSE_ROWS); \
|
|
156
|
+
\
|
|
157
|
+
kernel<<<cumo_launch_grid, cumo_launch_block>>>( \
|
|
158
|
+
__VA_ARGS__, cumo_launch_rows, cumo_launch_cols); \
|
|
159
|
+
} while (0)
|
|
160
|
+
|
|
65
161
|
static inline size_t
|
|
66
162
|
cumo_get_grid_dim(size_t n)
|
|
67
163
|
{
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
#include "half_def.h"
|
|
2
|
+
|
|
1
3
|
typedef CUMO_BIT_DIGIT dtype;
|
|
2
4
|
typedef CUMO_BIT_DIGIT rtype;
|
|
3
5
|
#define cT cumo_cBit
|
|
@@ -11,6 +13,7 @@ typedef CUMO_BIT_DIGIT rtype;
|
|
|
11
13
|
|
|
12
14
|
#define m_from_double(x) (((x)==0) ? 0 : 1)
|
|
13
15
|
#define m_from_real(x) (((x)==0) ? 0 : 1)
|
|
16
|
+
#define m_from_half(x) m_from_real(cumo_half2float(x))
|
|
14
17
|
#define m_from_sint(x) (((x)==0) ? 0 : 1)
|
|
15
18
|
#define m_from_int32(x) (((x)==0) ? 0 : 1)
|
|
16
19
|
#define m_from_int64(x) (((x)==0) ? 0 : 1)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#ifndef CUMO_BIT_KERNEL_H
|
|
2
2
|
#define CUMO_BIT_KERNEL_H
|
|
3
3
|
|
|
4
|
+
#include "half_def_kernel.h"
|
|
5
|
+
|
|
4
6
|
typedef CUMO_BIT_DIGIT dtype;
|
|
5
7
|
typedef CUMO_BIT_DIGIT rtype;
|
|
6
8
|
|
|
@@ -12,6 +14,7 @@ typedef CUMO_BIT_DIGIT rtype;
|
|
|
12
14
|
|
|
13
15
|
#define m_from_double(x) (((x)==0) ? 0 : 1)
|
|
14
16
|
#define m_from_real(x) (((x)==0) ? 0 : 1)
|
|
17
|
+
#define m_from_half(x) m_from_real(cumo_half2float(x))
|
|
15
18
|
#define m_from_sint(x) (((x)==0) ? 0 : 1)
|
|
16
19
|
#define m_from_int32(x) (((x)==0) ? 0 : 1)
|
|
17
20
|
#define m_from_int64(x) (((x)==0) ? 0 : 1)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "float_def.h"
|
|
2
|
+
#include "half_def.h"
|
|
2
3
|
|
|
3
4
|
extern double round(double);
|
|
4
5
|
extern double log2(double);
|
|
@@ -43,6 +44,7 @@ static inline dtype c_from_dcomplex(cumo_dcomplex x) {
|
|
|
43
44
|
|
|
44
45
|
#define m_from_double(x) c_new(x,0)
|
|
45
46
|
#define m_from_real(x) c_new(x,0)
|
|
47
|
+
#define m_from_half(x) m_from_real(cumo_half2float(x))
|
|
46
48
|
#define m_from_sint(x) c_new(x,0)
|
|
47
49
|
#define m_from_int32(x) c_new(x,0)
|
|
48
50
|
#define m_from_int64(x) c_new(x,0)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#define CUMO_COMPLEX_MACRO_KERNEL_H
|
|
3
3
|
|
|
4
4
|
#include "float_def_kernel.h"
|
|
5
|
+
#include "half_def_kernel.h"
|
|
5
6
|
|
|
6
7
|
extern double round(double);
|
|
7
8
|
extern double log2(double);
|
|
@@ -46,6 +47,7 @@ __host__ __device__ static inline dtype c_from_dcomplex(cumo_dcomplex x) {
|
|
|
46
47
|
|
|
47
48
|
#define m_from_double(x) c_new(x,0)
|
|
48
49
|
#define m_from_real(x) c_new(x,0)
|
|
50
|
+
#define m_from_half(x) m_from_real(cumo_half2float(x))
|
|
49
51
|
#define m_from_sint(x) c_new(x,0)
|
|
50
52
|
#define m_from_int32(x) c_new(x,0)
|
|
51
53
|
#define m_from_int64(x) c_new(x,0)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "float_def.h"
|
|
2
|
+
#include "half_def.h"
|
|
2
3
|
|
|
3
4
|
extern double round(double);
|
|
4
5
|
extern double log2(double);
|
|
@@ -17,6 +18,7 @@ extern double pow(double, double);
|
|
|
17
18
|
|
|
18
19
|
#define m_from_double(x) (x)
|
|
19
20
|
#define m_from_real(x) (x)
|
|
21
|
+
#define m_from_half(x) m_from_real(cumo_half2float(x))
|
|
20
22
|
#define m_from_sint(x) (x)
|
|
21
23
|
#define m_from_int32(x) (x)
|
|
22
24
|
#define m_from_int64(x) (x)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#define CUMO_FLOAT_MACRO_KERNEL_H
|
|
3
3
|
|
|
4
4
|
#include "float_def_kernel.h"
|
|
5
|
+
#include "half_def_kernel.h"
|
|
5
6
|
|
|
6
7
|
extern double round(double);
|
|
7
8
|
extern double log2(double);
|
|
@@ -20,6 +21,7 @@ extern double pow(double, double);
|
|
|
20
21
|
|
|
21
22
|
#define m_from_double(x) (x)
|
|
22
23
|
#define m_from_real(x) (x)
|
|
24
|
+
#define m_from_half(x) m_from_real(cumo_half2float(x))
|
|
23
25
|
#define m_from_sint(x) (x)
|
|
24
26
|
#define m_from_int32(x) (x)
|
|
25
27
|
#define m_from_int64(x) (x)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#ifndef CUMO_HALF_DEF_H
|
|
2
|
+
#define CUMO_HALF_DEF_H
|
|
3
|
+
|
|
4
|
+
// A struct rather than a bare uint16, so that C code which reaches for an
|
|
5
|
+
// arithmetic operator on an element fails to compile instead of computing on
|
|
6
|
+
// the bit pattern. Its layout matches __half, which the kernels use.
|
|
7
|
+
typedef struct { unsigned short x; } cumo_half;
|
|
8
|
+
|
|
9
|
+
// GCC gained _Float16 on x86-64 only in 12, and Ubuntu 22.04 ships 11, so the
|
|
10
|
+
// conversions are written out. Both round the way __float2half does, which
|
|
11
|
+
// test/hfloat_test.rb checks against the GPU over every 32-bit pattern.
|
|
12
|
+
static inline float cumo_half2float(cumo_half h)
|
|
13
|
+
{
|
|
14
|
+
union { unsigned int u; float f; } o;
|
|
15
|
+
unsigned int m = h.x & 0x3ffu;
|
|
16
|
+
unsigned int s = (unsigned int)(h.x & 0x8000u) << 16;
|
|
17
|
+
int e = (h.x >> 10) & 0x1f;
|
|
18
|
+
|
|
19
|
+
if (e == 0) {
|
|
20
|
+
if (m == 0) {
|
|
21
|
+
o.u = s;
|
|
22
|
+
return o.f;
|
|
23
|
+
}
|
|
24
|
+
e = 1;
|
|
25
|
+
while (!(m & 0x400u)) {
|
|
26
|
+
m <<= 1;
|
|
27
|
+
e--;
|
|
28
|
+
}
|
|
29
|
+
m &= 0x3ffu;
|
|
30
|
+
} else if (e == 31) {
|
|
31
|
+
o.u = s | 0x7f800000u | (m << 13);
|
|
32
|
+
return o.f;
|
|
33
|
+
}
|
|
34
|
+
o.u = s | ((unsigned int)(e + 112) << 23) | (m << 13);
|
|
35
|
+
return o.f;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static inline cumo_half cumo_float2half(float f)
|
|
39
|
+
{
|
|
40
|
+
union { unsigned int u; float f; } v;
|
|
41
|
+
cumo_half h;
|
|
42
|
+
unsigned int u, sign, mant, round_bits, shift, out;
|
|
43
|
+
int exp;
|
|
44
|
+
|
|
45
|
+
v.f = f;
|
|
46
|
+
u = v.u;
|
|
47
|
+
sign = (u >> 16) & 0x8000u;
|
|
48
|
+
u &= 0x7fffffffu;
|
|
49
|
+
|
|
50
|
+
if (u > 0x7f800000u) {
|
|
51
|
+
h.x = (unsigned short)(sign | 0x7e00u);
|
|
52
|
+
return h;
|
|
53
|
+
}
|
|
54
|
+
if (u >= 0x47800000u) {
|
|
55
|
+
h.x = (unsigned short)(sign | 0x7c00u);
|
|
56
|
+
return h;
|
|
57
|
+
}
|
|
58
|
+
if (u < 0x33000000u) {
|
|
59
|
+
h.x = (unsigned short)sign;
|
|
60
|
+
return h;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exp = (int)(u >> 23) - 127;
|
|
64
|
+
mant = u & 0x7fffffu;
|
|
65
|
+
if (exp >= -14) {
|
|
66
|
+
out = (unsigned int)(exp + 15) << 10;
|
|
67
|
+
shift = 13;
|
|
68
|
+
} else {
|
|
69
|
+
mant |= 0x800000u;
|
|
70
|
+
shift = (unsigned int)(-exp - 1);
|
|
71
|
+
out = 0;
|
|
72
|
+
}
|
|
73
|
+
round_bits = mant & ((1u << shift) - 1u);
|
|
74
|
+
out += mant >> shift;
|
|
75
|
+
if (round_bits > (1u << (shift - 1)) ||
|
|
76
|
+
(round_bits == (1u << (shift - 1)) && ((mant >> shift) & 1u))) {
|
|
77
|
+
out += 1;
|
|
78
|
+
}
|
|
79
|
+
h.x = (unsigned short)(sign | out);
|
|
80
|
+
return h;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static inline cumo_half cumo_double2half(double d)
|
|
84
|
+
{
|
|
85
|
+
union { unsigned long long u; double d; } v;
|
|
86
|
+
cumo_half h;
|
|
87
|
+
unsigned long long u, sign, mant, round_bits, tie;
|
|
88
|
+
unsigned int shift, out;
|
|
89
|
+
int exp;
|
|
90
|
+
|
|
91
|
+
v.d = d;
|
|
92
|
+
u = v.u;
|
|
93
|
+
sign = (u >> 48) & 0x8000ull;
|
|
94
|
+
u &= 0x7fffffffffffffffull;
|
|
95
|
+
|
|
96
|
+
if (u > 0x7ff0000000000000ull) {
|
|
97
|
+
h.x = (unsigned short)(sign | 0x7e00u);
|
|
98
|
+
return h;
|
|
99
|
+
}
|
|
100
|
+
if (u >= 0x40f0000000000000ull) {
|
|
101
|
+
h.x = (unsigned short)(sign | 0x7c00u);
|
|
102
|
+
return h;
|
|
103
|
+
}
|
|
104
|
+
if (u < 0x3e60000000000000ull) {
|
|
105
|
+
h.x = (unsigned short)sign;
|
|
106
|
+
return h;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
exp = (int)(u >> 52) - 1023;
|
|
110
|
+
mant = u & 0xfffffffffffffull;
|
|
111
|
+
if (exp >= -14) {
|
|
112
|
+
out = (unsigned int)(exp + 15) << 10;
|
|
113
|
+
shift = 42;
|
|
114
|
+
} else {
|
|
115
|
+
mant |= 0x10000000000000ull;
|
|
116
|
+
shift = (unsigned int)(28 - exp);
|
|
117
|
+
out = 0;
|
|
118
|
+
}
|
|
119
|
+
round_bits = mant & ((1ull << shift) - 1ull);
|
|
120
|
+
tie = 1ull << (shift - 1);
|
|
121
|
+
out += (unsigned int)(mant >> shift);
|
|
122
|
+
if (round_bits > tie || (round_bits == tie && ((mant >> shift) & 1ull))) {
|
|
123
|
+
out += 1;
|
|
124
|
+
}
|
|
125
|
+
h.x = (unsigned short)(sign | out);
|
|
126
|
+
return h;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
#endif // CUMO_HALF_DEF_H
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#ifndef CUMO_HALF_DEF_KERNEL_H
|
|
2
|
+
#define CUMO_HALF_DEF_KERNEL_H
|
|
3
|
+
|
|
4
|
+
#include <cuda_fp16.h>
|
|
5
|
+
|
|
6
|
+
typedef __half cumo_half;
|
|
7
|
+
|
|
8
|
+
// The arithmetic instructions on __half start at sm_53, but the conversions
|
|
9
|
+
// have no such floor, so every operation is computed in float. For + - * / and
|
|
10
|
+
// sqrt that answers what the native half instruction would: a float carries
|
|
11
|
+
// more than twice the bits of a half, so the second rounding cannot land on a
|
|
12
|
+
// tie the first one moved.
|
|
13
|
+
__host__ __device__ static inline float cumo_half2float(cumo_half h)
|
|
14
|
+
{
|
|
15
|
+
return __half2float(h);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
__host__ __device__ static inline cumo_half cumo_float2half(float f)
|
|
19
|
+
{
|
|
20
|
+
return __float2half(f);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
__host__ __device__ static inline cumo_half cumo_double2half(double d)
|
|
24
|
+
{
|
|
25
|
+
return __double2half(d);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#endif // CUMO_HALF_DEF_KERNEL_H
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#include "float_def.h"
|
|
2
|
+
#include "half_def.h"
|
|
3
|
+
|
|
4
|
+
#define CUMO_HALF_EPSILON 9.765625e-04f
|
|
5
|
+
|
|
6
|
+
#define m_zero cumo_float2half(0.0f)
|
|
7
|
+
#define m_one cumo_float2half(1.0f)
|
|
8
|
+
|
|
9
|
+
#define m_num_to_data(x) cumo_na_ruby_num_to_half(x)
|
|
10
|
+
#define m_data_to_num(x) rb_float_new(cumo_half2float(x))
|
|
11
|
+
|
|
12
|
+
#define m_from_double(x) cumo_double2half((double)(x))
|
|
13
|
+
#define m_from_real(x) cumo_double2half((double)(x))
|
|
14
|
+
#define m_from_sint(x) cumo_double2half((double)(x))
|
|
15
|
+
#define m_from_int32(x) cumo_double2half((double)(x))
|
|
16
|
+
#define m_from_int64(x) cumo_double2half((double)(x))
|
|
17
|
+
#define m_from_uint32(x) cumo_double2half((double)(x))
|
|
18
|
+
#define m_from_uint64(x) cumo_double2half((double)(x))
|
|
19
|
+
#define m_from_half(x) (x)
|
|
20
|
+
|
|
21
|
+
#define m_add(x,y) cumo_float2half(cumo_half2float(x)+cumo_half2float(y))
|
|
22
|
+
#define m_sub(x,y) cumo_float2half(cumo_half2float(x)-cumo_half2float(y))
|
|
23
|
+
#define m_mul(x,y) cumo_float2half(cumo_half2float(x)*cumo_half2float(y))
|
|
24
|
+
#define m_div(x,y) cumo_float2half(cumo_half2float(x)/cumo_half2float(y))
|
|
25
|
+
#define m_div_check(x,y) (cumo_half2float(y)==0)
|
|
26
|
+
|
|
27
|
+
static inline float cumo_half_floored_mod(float x, float y)
|
|
28
|
+
{
|
|
29
|
+
float r = fmodf(x,y);
|
|
30
|
+
if (r != 0 && ((r < 0) != (y < 0))) {
|
|
31
|
+
r += y;
|
|
32
|
+
}
|
|
33
|
+
return r;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#define m_mod(x,y) cumo_float2half(cumo_half_floored_mod(cumo_half2float(x),cumo_half2float(y)))
|
|
37
|
+
#define m_divmod(x,y,a,b) \
|
|
38
|
+
{float cumo_h_x = cumo_half2float(x), cumo_h_y = cumo_half2float(y); \
|
|
39
|
+
float cumo_h_b = fmodf(cumo_h_x,cumo_h_y); \
|
|
40
|
+
float cumo_h_a = roundf((cumo_h_x-cumo_h_b)/cumo_h_y); \
|
|
41
|
+
if (cumo_h_b != 0 && ((cumo_h_b < 0) != (cumo_h_y < 0))) { \
|
|
42
|
+
cumo_h_b += cumo_h_y; cumo_h_a -= 1; \
|
|
43
|
+
} \
|
|
44
|
+
a = cumo_float2half(cumo_h_a); b = cumo_float2half(cumo_h_b);}
|
|
45
|
+
#define m_pow(x,y) cumo_float2half(powf(cumo_half2float(x),cumo_half2float(y)))
|
|
46
|
+
#define m_pow_int(x,y) cumo_float2half(cumo_half_pow_int(cumo_half2float(x),(int)(y)))
|
|
47
|
+
|
|
48
|
+
#define m_abs(x) cumo_float2half(fabsf(cumo_half2float(x)))
|
|
49
|
+
#define m_minus(x) cumo_float2half(-cumo_half2float(x))
|
|
50
|
+
#define m_reciprocal(x) cumo_float2half(1.0f/cumo_half2float(x))
|
|
51
|
+
#define m_square(x) cumo_float2half(cumo_half2float(x)*cumo_half2float(x))
|
|
52
|
+
#define m_floor(x) cumo_float2half(floorf(cumo_half2float(x)))
|
|
53
|
+
#define m_round(x) cumo_float2half(roundf(cumo_half2float(x)))
|
|
54
|
+
#define m_ceil(x) cumo_float2half(ceilf(cumo_half2float(x)))
|
|
55
|
+
#define m_trunc(x) cumo_float2half(truncf(cumo_half2float(x)))
|
|
56
|
+
#define m_rint(x) cumo_float2half(rintf(cumo_half2float(x)))
|
|
57
|
+
#define m_sign(x) cumo_float2half(cumo_half_sign(cumo_half2float(x)))
|
|
58
|
+
#define m_copysign(x,y) cumo_float2half(copysignf(cumo_half2float(x),cumo_half2float(y)))
|
|
59
|
+
#define m_signbit(x) signbit(cumo_half2float(x))
|
|
60
|
+
#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);}
|
|
61
|
+
|
|
62
|
+
#define m_eq(x,y) (cumo_half2float(x)==cumo_half2float(y))
|
|
63
|
+
#define m_ne(x,y) (cumo_half2float(x)!=cumo_half2float(y))
|
|
64
|
+
#define m_gt(x,y) (cumo_half2float(x)>cumo_half2float(y))
|
|
65
|
+
#define m_ge(x,y) (cumo_half2float(x)>=cumo_half2float(y))
|
|
66
|
+
#define m_lt(x,y) (cumo_half2float(x)<cumo_half2float(y))
|
|
67
|
+
#define m_le(x,y) (cumo_half2float(x)<=cumo_half2float(y))
|
|
68
|
+
|
|
69
|
+
#define m_isnan(x) isnan(cumo_half2float(x))
|
|
70
|
+
#define m_isinf(x) isinf(cumo_half2float(x))
|
|
71
|
+
#define m_isposinf(x) (isinf(cumo_half2float(x)) && signbit(cumo_half2float(x))==0)
|
|
72
|
+
#define m_isneginf(x) (isinf(cumo_half2float(x)) && signbit(cumo_half2float(x)))
|
|
73
|
+
#define m_isfinite(x) isfinite(cumo_half2float(x))
|
|
74
|
+
|
|
75
|
+
#define not_nan(x) (cumo_half2float(x)==cumo_half2float(x))
|
|
76
|
+
|
|
77
|
+
#define m_mulsum_init INT2FIX(0)
|
|
78
|
+
|
|
79
|
+
#define m_sprintf(s,x) sprintf(s,"%g",cumo_half2float(x))
|
|
80
|
+
|
|
81
|
+
#define cmp_prnan(a,b) \
|
|
82
|
+
((cumo_half2float(qsort_cast(a))==cumo_half2float(qsort_cast(b))) ? 0 : \
|
|
83
|
+
(cumo_half2float(qsort_cast(a)) > cumo_half2float(qsort_cast(b))) ? 1 : -1)
|
|
84
|
+
|
|
85
|
+
#define cmp_ignan(a,b) \
|
|
86
|
+
(m_isnan(qsort_cast(a)) ? (m_isnan(qsort_cast(b)) ? 0 : 1) : \
|
|
87
|
+
(m_isnan(qsort_cast(b)) ? -1 : \
|
|
88
|
+
((cumo_half2float(qsort_cast(a))==cumo_half2float(qsort_cast(b))) ? 0 : \
|
|
89
|
+
(cumo_half2float(qsort_cast(a)) > cumo_half2float(qsort_cast(b))) ? 1 : -1)))
|
|
90
|
+
|
|
91
|
+
#define cmpgt_prnan(a,b) \
|
|
92
|
+
(cumo_half2float(qsort_cast(a)) > cumo_half2float(qsort_cast(b)))
|
|
93
|
+
|
|
94
|
+
#define cmpgt_ignan(a,b) \
|
|
95
|
+
((m_isnan(qsort_cast(a)) && !m_isnan(qsort_cast(b))) || \
|
|
96
|
+
(cumo_half2float(qsort_cast(a)) > cumo_half2float(qsort_cast(b))))
|
|
97
|
+
|
|
98
|
+
#define m_sqrt(x) cumo_float2half(sqrtf(cumo_half2float(x)))
|
|
99
|
+
#define m_cbrt(x) cumo_float2half(cbrtf(cumo_half2float(x)))
|
|
100
|
+
#define m_log(x) cumo_float2half(logf(cumo_half2float(x)))
|
|
101
|
+
#define m_log2(x) cumo_float2half(log2f(cumo_half2float(x)))
|
|
102
|
+
#define m_log10(x) cumo_float2half(log10f(cumo_half2float(x)))
|
|
103
|
+
#define m_exp(x) cumo_float2half(expf(cumo_half2float(x)))
|
|
104
|
+
#define m_exp2(x) cumo_float2half(exp2f(cumo_half2float(x)))
|
|
105
|
+
#ifdef HAVE_EXP10
|
|
106
|
+
#define m_exp10(x) cumo_float2half(exp10f(cumo_half2float(x)))
|
|
107
|
+
#else
|
|
108
|
+
#define m_exp10(x) cumo_float2half(powf(10.0f,cumo_half2float(x)))
|
|
109
|
+
#endif
|
|
110
|
+
#define m_expm1(x) cumo_float2half(expm1f(cumo_half2float(x)))
|
|
111
|
+
#define m_log1p(x) cumo_float2half(log1pf(cumo_half2float(x)))
|
|
112
|
+
|
|
113
|
+
#define m_sin(x) cumo_float2half(sinf(cumo_half2float(x)))
|
|
114
|
+
#define m_cos(x) cumo_float2half(cosf(cumo_half2float(x)))
|
|
115
|
+
#define m_tan(x) cumo_float2half(tanf(cumo_half2float(x)))
|
|
116
|
+
#define m_asin(x) cumo_float2half(asinf(cumo_half2float(x)))
|
|
117
|
+
#define m_acos(x) cumo_float2half(acosf(cumo_half2float(x)))
|
|
118
|
+
#define m_atan(x) cumo_float2half(atanf(cumo_half2float(x)))
|
|
119
|
+
#define m_sinh(x) cumo_float2half(sinhf(cumo_half2float(x)))
|
|
120
|
+
#define m_cosh(x) cumo_float2half(coshf(cumo_half2float(x)))
|
|
121
|
+
#define m_tanh(x) cumo_float2half(tanhf(cumo_half2float(x)))
|
|
122
|
+
#define m_asinh(x) cumo_float2half(asinhf(cumo_half2float(x)))
|
|
123
|
+
#define m_acosh(x) cumo_float2half(acoshf(cumo_half2float(x)))
|
|
124
|
+
#define m_atanh(x) cumo_float2half(atanhf(cumo_half2float(x)))
|
|
125
|
+
#define m_atan2(x,y) cumo_float2half(atan2f(cumo_half2float(x),cumo_half2float(y)))
|
|
126
|
+
#define m_hypot(x,y) cumo_float2half(hypotf(cumo_half2float(x),cumo_half2float(y)))
|
|
127
|
+
#define m_sinc(x) cumo_float2half(cumo_half_sinc(cumo_half2float(x)))
|
|
128
|
+
|
|
129
|
+
#define m_erf(x) cumo_float2half(erff(cumo_half2float(x)))
|
|
130
|
+
#define m_erfc(x) cumo_float2half(erfcf(cumo_half2float(x)))
|
|
131
|
+
#define m_ldexp(x,y) cumo_float2half(cumo_half_ldexp(cumo_half2float(x),cumo_half2float(y)))
|
|
132
|
+
#define m_frexp(x,exp) cumo_float2half(frexpf(cumo_half2float(x),exp))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
static inline float cumo_half_pow_positive_int(float x, unsigned int p)
|
|
136
|
+
{
|
|
137
|
+
float r = 1.0f;
|
|
138
|
+
switch (p) {
|
|
139
|
+
case 0: return 1.0f;
|
|
140
|
+
case 1: return x;
|
|
141
|
+
case 2: return x*x;
|
|
142
|
+
case 3: return x*x*x;
|
|
143
|
+
case 4: x = x*x; return x*x;
|
|
144
|
+
}
|
|
145
|
+
if (p > 64) return powf(x, (float)p);
|
|
146
|
+
while (p) {
|
|
147
|
+
if (p & 1) r *= x;
|
|
148
|
+
x *= x;
|
|
149
|
+
p >>= 1;
|
|
150
|
+
}
|
|
151
|
+
return r;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static inline float cumo_half_pow_int(float x, int p)
|
|
155
|
+
{
|
|
156
|
+
if (p < 0) return 1.0f / cumo_half_pow_positive_int(x, -(unsigned int)p);
|
|
157
|
+
return cumo_half_pow_positive_int(x, (unsigned int)p);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static inline float cumo_half_ldexp(float x, float y)
|
|
161
|
+
{
|
|
162
|
+
if (!(y == y)) return y;
|
|
163
|
+
if (y > 64.0f) y = 64.0f;
|
|
164
|
+
if (y < -64.0f) y = -64.0f;
|
|
165
|
+
return ldexpf(x, (int)y);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static inline float cumo_half_sinc(float x)
|
|
169
|
+
{
|
|
170
|
+
return (x==0) ? 1.0f : (sinf(x)/x);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static inline float cumo_half_sign(float x)
|
|
174
|
+
{
|
|
175
|
+
return (x==0) ? 0.0f : ((x>0) ? 1.0f : ((x<0) ? -1.0f : x));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
static inline cumo_half cumo_na_ruby_num_to_half(VALUE x)
|
|
179
|
+
{
|
|
180
|
+
return cumo_double2half(NIL_P(x) ? nan("") : NUM2DBL(x));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static inline cumo_half f_seq(cumo_half x, cumo_half y, double c)
|
|
184
|
+
{
|
|
185
|
+
return cumo_float2half(cumo_half2float(x) + cumo_half2float(y) * (float)c);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
#include "real_accum.h"
|