Помогите разобраться с программой, пожалуйста [RNG, SSE2]

dimi61

Программа описана в этой статье: http://software.intel.com/en-us/articles/fast-random-number-...
Вот в таком виде я ее использую в GCC:

#include <emmintrin.h>

#ifdef _MSC_VER
# define ALIGN16 __declspec( align(16) )
#elif defined __GNUC__
# define ALIGN16 __attribute__aligned(16
#endif

ALIGN16 static __m128i g_randsse_seed;

inline void srand_sse( unsigned int seed )
{
g_randsse_seed = _mm_set_epi32( seed, seed+1, seed, seed+1 );
}

inline void rand_sse128( unsigned int* result )
{
ALIGN16 __m128i cur_seed_split;
ALIGN16 __m128i multiplier;
ALIGN16 __m128i adder;
ALIGN16 __m128i mod_mask;
ALIGN16 __m128i sra_mask;
ALIGN16 __m128i sseresult;
ALIGN16 static const unsigned int mult[4] = { 214013, 17405, 214013, 69069 };
ALIGN16 static const unsigned int gadd[4] = { 2531011, 10395331, 13737667, 1 };
ALIGN16 static const unsigned int mask[4] = { 0xFFFFFFFF, 0, 0xFFFFFFFF, 0 };
ALIGN16 static const unsigned int masklo[4] = { 0x00007FFF, 0x00007FFF, 0x00007FFF, 0x00007FFF };

adder = _mm_load_si128( (__m128i*) gadd);
multiplier = _mm_load_si128( (__m128i*) mult);
mod_mask = _mm_load_si128( (__m128i*) mask);
sra_mask = _mm_load_si128( (__m128i*) masklo);
cur_seed_split = _mm_shuffle_epi32( g_randsse_seed, _MM_SHUFFLE( 2, 3, 0, 1 ) );

g_randsse_seed = _mm_mul_epu32( g_randsse_seed, multiplier );
multiplier = _mm_shuffle_epi32( multiplier, _MM_SHUFFLE( 2, 3, 0, 1 ) );
cur_seed_split = _mm_mul_epu32( cur_seed_split, multiplier );

g_randsse_seed = _mm_and_si128( g_randsse_seed, mod_mask);
cur_seed_split = _mm_and_si128( cur_seed_split, mod_mask );
cur_seed_split = _mm_shuffle_epi32( cur_seed_split, _MM_SHUFFLE( 2, 3, 0, 1 ) );
g_randsse_seed = _mm_or_si128( g_randsse_seed, cur_seed_split );
g_randsse_seed = _mm_add_epi32( g_randsse_seed, adder);

_mm_storeu_si128( (__m128i*) result, g_randsse_seed);
return;
}

Вопросы:
1) сгенерированное значение будет записываться по адресу, где, с точки зрения функции, лежит 128-битное целое? Или 32-битное? Сколько бит туда запишется?
2) Если, допустим, меня устроят 8-битные псевдослучайные числа, причем супервысокой случайности от них не требуется (например, уровня стандартного rand вполне сойдет). Могу ли я писать в 32-битное (128-битное) целое сгенеренное число, а затем забирать из него четверку (или 16) чаров и трактовать их как случайные?

Dasar

1. google: _mm_storeu_si128
Stores 128-bit value.
2. если это нормальный random, то - да, можно использовать только часть битов.

Serab

Странно, второй вопрос же чисто математический. Можно доказать, что равномерная распределенность между 0 и 2^k-1 для любого k равносильна одинаковой и независимой распределенности каждого из k битов. Отсюда следует, что можно использовать любые 8 бит.

Serab

сигнатура у функции, конечно, ужасная. Лучше уж честно написать void*. А то передашь адрес переменной на стеке у получишь красивые спецэффекты.

dimi61

Огромное спасибо.

procenkotanya

Лучше уж честно написать void*
И чем это честнее и лучше? Если пишется выровненный __int128, надо так и писать.

Serab

Тем, что если написано unsigned int*, то однозначно намекается на то, что запишется sizeof(unsigned). А если void* — это уже повод задуматься. Тем лучше. Настоящий тип написать еще лучше, да.

Marinavo_0507

если написано unsigned int*, то однозначно намекается на то, что запишется sizeof(unsigned)
а как тогда намекнуть, что запишется массив из unsigned ?

Serab

передать unsigned *length
Оставить комментарий
Имя или ник:
Комментарий: