(正確かつ有益な回答、以下を参照)
私は、matlab と gpu (nvidia gtx660) で実験を始めています。
ここで、PI を計算するためのこの単純なモンテカルロ アルゴリズムを作成しました。CPU のバージョンは次のとおりです。
function pig = mc1vecnocuda(n)
countr=0;
A=rand(n,2);
for i=1:n
if norm(A(i,:))<1
countr=countr+1;
end
end
pig=(countr/n)*4;
end
これは、100000 ポイントが単位円に「投入」された CPU で実行されるのにほとんど時間がかかりません。
>> tic; mc1vecnocuda(100000);toc;
Elapsed time is 0.092473 seconds.
代わりに、GPU 化されたバージョンのアルゴリズムで何が起こるかを見てください。
function pig = mc1veccuda(n)
countr=0;
gpucountr=gpuArray(countr);
A=gpuArray.rand(n,2);
parfor (i=1:n,1024)
if norm(A(i,:))<1
gpucountr=gpucountr+1;
end
end
pig=(gpucountr/n)*4;
end
さて、これは実行に長い時間がかかります:
>> tic; mc1veccuda(100000);toc;
Elapsed time is 21.137954 seconds.
理由がわかりません。1024 個のワーカーで parfor ループを使用しました。これは、gpuDevice で nvidia カードをクエリすると、gtx660 で許可される同時スレッドの最大数が 1024 になるためです。
誰かが私を助けることができますか?ありがとう。
編集:これはIFを回避する更新版です:
function pig = mc2veccuda(n)
countr=0;
gpucountr=gpuArray(countr);
A=gpuArray.rand(n,2);
parfor (i=1:n,1024)
gpucountr = gpucountr+nnz(norm(A(i,:))<1);
end
pig=(gpucountr/n)*4;
end
そして、これは Bichoy のガイドラインに従って書かれたコードです (結果を達成するための 正しいコード):
function pig = mc3veccuda(n)
countr=0;
gpucountr=gpuArray(countr);
A=gpuArray.rand(n,2);
Asq = A.^2;
Asqsum_big_column = Asq(:,1)+Asq(:,2);
Anorms=Asqsum_big_column.^(1/2);
gpucountr=gpucountr+nnz(Anorms<1);
pig=(gpucountr/n)*4;
end
n=1000万の実行時間に注意してください:
>> tic; mc3veccuda(10000000); toc;
Elapsed time is 0.131348 seconds.
>> tic; mc1vecnocuda(10000000); toc;
Elapsed time is 8.108907 seconds.
元の cuda バージョン (for/parfor) はテストしませんでした。実行には n=10000000 の場合、数時間かかるからです。
グレートビチョイ!;)