Я решал эту «не случайную» проблему в течение последних нескольких дней, и я предложил три различных подхода:
Xorshift - Я создал генератор на основе этого. Все, что вам нужно сделать, это предоставить один uint2
номер (семя) для всего ядра, и каждый рабочий элемент будет вычислять свой собственный номер ранда
// 'randoms' is uint2 passed to kernel
uint seed = randoms.x + globalID;
uint t = seed ^ (seed << 11);
uint result = randoms.y ^ (randoms.y >> 19) ^ (t ^ (t >> 8));
Java random - Я использовал код из метода .next(int bits)
для генерации случайного числа. На этот раз вы должны предоставить один ulong
номер в качестве начального числа.
// 'randoms' is ulong passed to kernel
ulong seed = randoms + globalID;
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
uint result = seed >> 16;
Просто сгенерируйте все на процессоре и передайте ядру в один большой буфер.
Я протестировал все три подхода (генераторы) в своем алгоритме эволюции, вычисляя минимальный доминирующий набор в графах.
Мне нравятся сгенерированные числа из первого, но, похоже, мой алгоритм эволюции - нет.
Второй генератор генерирует числа, которые имеют некоторый видимый паттерн, но моему алгоритму эволюции это нравится в любом случае, и все работает немного быстрее, чем с первым генератором.
Но третий подход показывает, что абсолютно просто предоставить все номера с хоста (процессора). Сначала я подумал, что генерация (в моем случае) 1536 номеров int32 и передача их в GPU при каждом вызове ядра будет слишком дорогой (для вычисления и передачи в GPU). Но, оказывается, это так же быстро, как мои предыдущие попытки. И загрузка процессора остается ниже 5%.
Кстати, я также пытался MWC64X Random , но после того, как я установил новый драйвер графического процессора, функция mul_hi
начинает вызывать сбой сборки (даже весь AMD Kernel Analyer зависал).