と の間の乱数0.0
を1.0
使用してベクトルを生成する必要がありThrust
ます。私が見つけた唯一の文書化された例は、非常に大きな乱数を生成します ( thrust::generate(myvector.begin(), myvector.end(), rand
)。答えは簡単だと思いますが、何か提案をいただければ幸いです。
4 に答える
Thrust には、一連の乱数を生成するために使用できる乱数発生器があります。それらをデバイス ベクトルで使用するには、ランダム ジェネレーター シーケンスの別の要素を返すファンクターを作成する必要があります。これを行う最も簡単な方法は、カウント反復子の変換を使用することです。非常に単純な完全な例 (この場合、1.0 から 2.0 の間のランダムな単精度数を生成する) は次のようになります。
#include <thrust/random.h>
#include <thrust/device_vector.h>
#include <thrust/transform.h>
#include <thrust/iterator/counting_iterator.h>
#include <iostream>
struct prg
{
float a, b;
__host__ __device__
prg(float _a=0.f, float _b=1.f) : a(_a), b(_b) {};
__host__ __device__
float operator()(const unsigned int n) const
{
thrust::default_random_engine rng;
thrust::uniform_real_distribution<float> dist(a, b);
rng.discard(n);
return dist(rng);
}
};
int main(void)
{
const int N = 20;
thrust::device_vector<float> numbers(N);
thrust::counting_iterator<unsigned int> index_sequence_begin(0);
thrust::transform(index_sequence_begin,
index_sequence_begin + N,
numbers.begin(),
prg(1.f,2.f));
for(int i = 0; i < N; i++)
{
std::cout << numbers[i] << std::endl;
}
return 0;
}
この例では、ファンクターprg
は乱数の下限と上限を(0.f,1.f)
デフォルトの引数として受け取ります。変換操作を呼び出すたびに異なるベクトルを取得するには、異なる開始値に初期化されたカウント反復子を使用する必要があることに注意してください。
あなたの質問に対する直接的な答えではないかもしれませんが、cuRand ライブラリはこの概念において非常に強力です。GPU と CPU の両方で乱数を生成することができ、多くの分布関数 (正規分布など) が含まれています。
次のリンクで「An NVIDIA CURAND implementation」というタイトルを検索してください: http://adnanboz.wordpress.com/tag/nvidia-curand/
//Create a new generator
curandCreateGenerator(&m_prng, CURAND_RNG_PSEUDO_DEFAULT);
//Set the generator options
curandSetPseudoRandomGeneratorSeed(m_prng, (unsigned long) mainSeed);
//Generate random numbers
curandGenerateUniform(m_prng, d_randomData, dataCount);
1 つの注意点として、ジェネレーターを何度も生成しないでください。いくつかの事前計算が行われます。curandGenerateUniform の呼び出しは非常に高速で、0.0 から 1.0 の間の値を生成します。
@talonmies によって提案されたアプローチには、多くの有用な特徴があります。引用した例を模倣する別のアプローチを次に示します。
#include <thrust/host_vector.h>
#include <thrust/generate.h>
#include <iostream>
#define DSIZE 5
__host__ static __inline__ float rand_01()
{
return ((float)rand()/RAND_MAX);
}
int main(){
thrust::host_vector<float> h_1(DSIZE);
thrust::generate(h_1.begin(), h_1.end(), rand_01);
std::cout<< "Values generated: " << std::endl;
for (unsigned i=0; i<DSIZE; i++)
std::cout<< h_1[i] << " : ";
std::cout<<std::endl;
return 0;
}
引用した例と同様に、これは rand() を使用するため、ホストベクターの生成にのみ使用できます。同様に、rand() を適切に再シードしない限り、毎回同じシーケンスが生成されます。