55 #ifndef ROCRAND_MTGP32_H_
56 #define ROCRAND_MTGP32_H_
58 #include "rocrand/rocrand.h"
60 #include <hip/hip_runtime.h>
65 #define MTGP_MEXP 11213
67 #define MTGP_FLOOR_2P 256
68 #define MTGP_CEIL_2P 512
69 #define MTGP_TN MTGP_FLOOR_2P
70 #define MTGP_LS (MTGP_TN * 3)
71 #define MTGP_BN_MAX 512
73 #define MTGP_STATE 1024
74 #define MTGP_MASK 1023
109 namespace rocrand_device {
113 unsigned int pos_tbl[MTGP_BN_MAX];
114 unsigned int param_tbl[MTGP_BN_MAX][MTGP_TS];
115 unsigned int temper_tbl[MTGP_BN_MAX][MTGP_TS];
116 unsigned int single_temper_tbl[MTGP_BN_MAX][MTGP_TS];
117 unsigned int sh1_tbl[MTGP_BN_MAX];
118 unsigned int sh2_tbl[MTGP_BN_MAX];
119 unsigned int mask[1];
128 unsigned int status[MTGP_STATE];
132 void rocrand_mtgp32_init_state(
unsigned int array[],
133 const mtgp32_fast_params *para,
unsigned int seed)
136 int size = para->mexp / 32 + 1;
137 unsigned int hidden_seed;
139 hidden_seed = para->tbl[4] ^ (para->tbl[8] << 16);
143 memset(array, tmp & 0xff,
sizeof(
unsigned int) * size);
145 array[1] = hidden_seed;
146 for (i = 1; i < size; i++)
147 array[i] ^= (1812433253) * (array[i - 1] ^ (array[i - 1] >> 30)) + i;
153 __forceinline__ __device__ __host__
160 __forceinline__ __device__ __host__ mtgp32_engine(
const mtgp32_state& m_state,
161 const mtgp32_params* params,
164 this->m_state = m_state;
165 pos_tbl = params->pos_tbl[bid];
166 sh1_tbl = params->sh1_tbl[bid];
167 sh2_tbl = params->sh2_tbl[bid];
168 mask = params->mask[0];
169 for (
int j = 0; j < MTGP_TS; j++) {
170 param_tbl[j] = params->param_tbl[bid][j];
171 temper_tbl[j] = params->temper_tbl[bid][j];
172 single_temper_tbl[j] = params->single_temper_tbl[bid][j];
176 __forceinline__ __device__ __host__
void copy(
const mtgp32_engine* m_engine)
178 #if defined(__HIP_DEVICE_COMPILE__)
179 const unsigned int thread_id = threadIdx.x;
180 for(
int i = thread_id; i < MTGP_STATE; i += blockDim.x)
181 m_state.status[i] = m_engine->m_state.status[i];
185 m_state.offset = m_engine->m_state.offset;
186 m_state.id = m_engine->m_state.id;
187 pos_tbl = m_engine->pos_tbl;
188 sh1_tbl = m_engine->sh1_tbl;
189 sh2_tbl = m_engine->sh2_tbl;
190 mask = m_engine->mask;
192 if (thread_id < MTGP_TS)
194 param_tbl[thread_id] = m_engine->param_tbl[thread_id];
195 temper_tbl[thread_id] = m_engine->temper_tbl[thread_id];
196 single_temper_tbl[thread_id] = m_engine->single_temper_tbl[thread_id];
200 this->m_state = m_engine->m_state;
201 pos_tbl = m_engine->pos_tbl;
202 sh1_tbl = m_engine->sh1_tbl;
203 sh2_tbl = m_engine->sh2_tbl;
204 mask = m_engine->mask;
205 for (
int j = 0; j < MTGP_TS; j++) {
206 param_tbl[j] = m_engine->param_tbl[j];
207 temper_tbl[j] = m_engine->temper_tbl[j];
208 single_temper_tbl[j] = m_engine->single_temper_tbl[j];
213 __forceinline__ __device__ __host__
void set_params(mtgp32_params* params)
215 pos_tbl = params->pos_tbl[m_state.id];
216 sh1_tbl = params->sh1_tbl[m_state.id];
217 sh2_tbl = params->sh2_tbl[m_state.id];
218 mask = params->mask[0];
219 for (
int j = 0; j < MTGP_TS; j++) {
220 param_tbl[j] = params->param_tbl[m_state.id][j];
221 temper_tbl[j] = params->temper_tbl[m_state.id][j];
222 single_temper_tbl[j] = params->single_temper_tbl[m_state.id][j];
226 __forceinline__ __device__ __host__
unsigned int operator()()
231 __forceinline__ __device__ __host__
unsigned int next()
233 #ifdef __HIP_DEVICE_COMPILE__
234 unsigned int o = next_thread(threadIdx.x);
238 m_state.offset = (m_state.offset + blockDim.x) & MTGP_MASK;
247 __forceinline__ __device__ __host__
unsigned int next_single()
249 #if defined(__HIP_DEVICE_COMPILE__)
250 unsigned int t = threadIdx.x;
251 unsigned int d = blockDim.x;
256 r = para_rec(m_state.status[(t + m_state.offset) & MTGP_MASK],
257 m_state.status[(t + m_state.offset + 1) & MTGP_MASK],
258 m_state.status[(t + m_state.offset + pos) & MTGP_MASK]);
259 m_state.status[(t + m_state.offset + MTGP_N) & MTGP_MASK] = r;
261 o = temper_single(r, m_state.status[(t + m_state.offset + pos - 1) & MTGP_MASK]);
264 m_state.offset = (m_state.offset + d) & MTGP_MASK;
273 __forceinline__ __device__ __host__
unsigned int
274 para_rec(
unsigned int X1,
unsigned int X2,
unsigned int Y)
const
276 unsigned int X = (X1 & mask) ^ X2;
280 Y = X ^ (Y >> sh2_tbl);
281 MAT = param_tbl[Y & 0x0f];
285 __forceinline__ __device__ __host__
unsigned int temper(
unsigned int V,
unsigned int T)
const
291 MAT = temper_tbl[T & 0x0f];
295 __forceinline__ __device__ __host__
unsigned int temper_single(
unsigned int V,
296 unsigned int T)
const
303 MAT = single_temper_tbl[T & 0x0f];
311 __forceinline__ __device__ __host__
unsigned int next_thread(
unsigned int thread_idx)
314 = para_rec(m_state.status[(thread_idx + m_state.offset) & MTGP_MASK],
315 m_state.status[(thread_idx + m_state.offset + 1) & MTGP_MASK],
316 m_state.status[(thread_idx + m_state.offset + pos_tbl) & MTGP_MASK]);
317 m_state.status[(thread_idx + m_state.offset + MTGP_N) & MTGP_MASK] = r;
318 return temper(r, m_state.status[(thread_idx + m_state.offset + pos_tbl - 1) & MTGP_MASK]);
323 mtgp32_state m_state;
325 unsigned int pos_tbl;
326 unsigned int param_tbl[MTGP_TS];
327 unsigned int temper_tbl[MTGP_TS];
328 unsigned int sh1_tbl;
329 unsigned int sh2_tbl;
330 unsigned int single_temper_tbl[MTGP_TS];
343 typedef rocrand_device::mtgp32_engine rocrand_state_mtgp32;
344 typedef rocrand_device::mtgp32_state mtgp32_state;
346 typedef rocrand_device::mtgp32_params mtgp32_params;
366 mtgp32_fast_params params[],
368 unsigned long long seed)
371 rocrand_state_mtgp32 * h_state = (rocrand_state_mtgp32 *) malloc(
sizeof(rocrand_state_mtgp32) * n);
372 seed = seed ^ (seed >> 32);
377 for (i = 0; i < n; i++) {
378 rocrand_device::rocrand_mtgp32_init_state(&(h_state[i].m_state.status[0]), ¶ms[i], (
unsigned int)seed + i + 1);
379 h_state[i].m_state.offset = 0;
380 h_state[i].m_state.id = i;
381 h_state[i].pos_tbl = params[i].pos;
382 h_state[i].sh1_tbl = params[i].sh1;
383 h_state[i].sh2_tbl = params[i].sh2;
384 h_state[i].mask = params[0].mask;
385 for (
int j = 0; j < MTGP_TS; j++) {
386 h_state[i].param_tbl[j] = params[i].tbl[j];
387 h_state[i].temper_tbl[j] = params[i].tmp_tbl[j];
388 h_state[i].single_temper_tbl[j] = params[i].flt_tmp_tbl[j];
392 const hipError_t error
393 = hipMemcpy(state, h_state,
sizeof(rocrand_state_mtgp32) * n, hipMemcpyDefault);
396 if(error != hipSuccess)
421 const int block_num = MTGP_BN_MAX;
422 const int size1 =
sizeof(uint32_t) * block_num;
423 const int size2 =
sizeof(uint32_t) * block_num * MTGP_TS;
427 uint32_t *h_param_tbl;
428 uint32_t *h_temper_tbl;
429 uint32_t *h_single_temper_tbl;
431 h_pos_tbl = (uint32_t *)malloc(size1);
432 h_sh1_tbl = (uint32_t *)malloc(size1);
433 h_sh2_tbl = (uint32_t *)malloc(size1);
434 h_param_tbl = (uint32_t *)malloc(size2);
435 h_temper_tbl = (uint32_t *)malloc(size2);
436 h_single_temper_tbl = (uint32_t *)malloc(size2);
437 h_mask = (uint32_t *)malloc(
sizeof(uint32_t));
440 if (h_pos_tbl == NULL || h_sh1_tbl == NULL || h_sh2_tbl == NULL
441 || h_param_tbl == NULL || h_temper_tbl == NULL || h_single_temper_tbl == NULL
443 printf(
"failure in allocating host memory for constant table.\n");
447 h_mask[0] = params[0].mask;
448 for (
int i = 0; i < block_num; i++) {
449 h_pos_tbl[i] = params[i].pos;
450 h_sh1_tbl[i] = params[i].sh1;
451 h_sh2_tbl[i] = params[i].sh2;
452 for (
int j = 0; j < MTGP_TS; j++) {
453 h_param_tbl[i * MTGP_TS + j] = params[i].tbl[j];
454 h_temper_tbl[i * MTGP_TS + j] = params[i].tmp_tbl[j];
455 h_single_temper_tbl[i * MTGP_TS + j] = params[i].flt_tmp_tbl[j];
459 if (hipMemcpy(p->pos_tbl, h_pos_tbl, size1, hipMemcpyHostToDevice) != hipSuccess)
461 if (hipMemcpy(p->sh1_tbl, h_sh1_tbl, size1, hipMemcpyHostToDevice) != hipSuccess)
463 if (hipMemcpy(p->sh2_tbl, h_sh2_tbl, size1, hipMemcpyHostToDevice) != hipSuccess)
465 if (hipMemcpy(p->param_tbl, h_param_tbl, size2, hipMemcpyHostToDevice) != hipSuccess)
467 if (hipMemcpy(p->temper_tbl, h_temper_tbl, size2, hipMemcpyHostToDevice) != hipSuccess)
469 if (hipMemcpy(p->single_temper_tbl, h_single_temper_tbl, size2, hipMemcpyHostToDevice) != hipSuccess)
471 if (hipMemcpy(p->mask, h_mask,
sizeof(
unsigned int), hipMemcpyHostToDevice) != hipSuccess)
480 free(h_single_temper_tbl);
498 __forceinline__ __device__
499 unsigned int rocrand(rocrand_state_mtgp32* state)
501 return state->next();
535 __forceinline__ __device__
547 __forceinline__ __device__
550 state->set_params(params);
__forceinline__ __device__ void rocrand_mtgp32_block_copy(rocrand_state_mtgp32 *src, rocrand_state_mtgp32 *dest)
Copies MTGP32 state to another state using block of threads.
Definition: rocrand_mtgp32.h:536
__host__ rocrand_status rocrand_make_state_mtgp32(rocrand_state_mtgp32 *state, mtgp32_fast_params params[], int n, unsigned long long seed)
Initializes MTGP32 states.
Definition: rocrand_mtgp32.h:365
__forceinline__ __device__ unsigned int rocrand(rocrand_state_mtgp32 *state)
Returns uniformly distributed random unsigned int value from [0; 2^32 - 1] range.
Definition: rocrand_mtgp32.h:499
__host__ rocrand_status rocrand_make_constant(const mtgp32_fast_params params[], mtgp32_params *p)
Loads parameters for MTGP32.
Definition: rocrand_mtgp32.h:419
__forceinline__ __device__ void rocrand_mtgp32_set_params(rocrand_state_mtgp32 *state, mtgp32_params *params)
Changes parameters of a MTGP32 state.
Definition: rocrand_mtgp32.h:548
rocrand_status
rocRAND function call status type
Definition: rocrand.h:61
@ ROCRAND_STATUS_SUCCESS
No errors.
Definition: rocrand.h:62
@ ROCRAND_STATUS_ALLOCATION_FAILED
Memory allocation failed during execution.
Definition: rocrand.h:65
Definition: rocrand_mtgp32.h:97
uint32_t tmp_tbl[16]
Definition: rocrand_mtgp32.h:103
int pos
Definition: rocrand_mtgp32.h:99
int mexp
Definition: rocrand_mtgp32.h:98
int sh2
Definition: rocrand_mtgp32.h:101
int sh1
Definition: rocrand_mtgp32.h:100
uint32_t mask
Definition: rocrand_mtgp32.h:105
unsigned char poly_sha1[21]
Definition: rocrand_mtgp32.h:106
uint32_t tbl[16]
Definition: rocrand_mtgp32.h:102
uint32_t flt_tmp_tbl[16]
Definition: rocrand_mtgp32.h:104