私は次のコードを持っています
#include <iostream>
#include <cuda.h>
#include <cuda_runtime.h>
#include <ctime>
#include <vector>
#include <numeric>
float random_float(void)
{
return static_cast<float>(rand()) / RAND_MAX;
}
std::vector<float> add(float alpha, std::vector<float>& v1, std::vector<float>& v2 )
{ /*Do quick size check on vectors before proceeding*/
std::vector<float> result(v1.size());
for (unsigned int i = 0; i < result.size(); ++i)
{
result[i]=alpha*v1[i]+v2[i];
}
return result;
}
__global__ void Addloop( int N, float alpha, float* x, float* y ) {
int i;
int i0 = blockIdx.x*blockDim.x + threadIdx.x;
for( i = i0; i < N; i += blockDim.x*gridDim.x )
y[i] = alpha*x[i] + y[i];
/*
if ( i0 < N )
y[i0] = alpha*x[i0] + y[i0];
*/
}
int main( int argc, char** argv ) {
float alpha = 0.3;
// create array of 256k elements
int num_elements = 10;//1<<18;
// generate random input on the host
std::vector<float> h1_input(num_elements);
std::vector<float> h2_input(num_elements);
for(int i = 0; i < num_elements; ++i)
{
h1_input[i] = random_float();
h2_input[i] = random_float();
}
for (std::vector<float>::iterator it = h1_input.begin() ; it != h1_input.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
for (std::vector<float>::iterator it = h2_input.begin() ; it != h2_input.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::vector<float> host_result;//(std::vector<float> h1_input, std::vector<float> h2_input );
host_result = add( alpha, h1_input, h2_input );
for (std::vector<float>::iterator it = host_result.begin() ; it != host_result.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
// move input to device memory
float *d1_input = 0;
cudaMalloc((void**)&d1_input, sizeof(float) * num_elements);
cudaMemcpy(d1_input, &h1_input[0], sizeof(float) * num_elements, cudaMemcpyHostToDevice);
float *d2_input = 0;
cudaMalloc((void**)&d2_input, sizeof(float) * num_elements);
cudaMemcpy(d2_input, &h2_input[0], sizeof(float) * num_elements, cudaMemcpyHostToDevice);
Addloop<<<1,3>>>( num_elements, alpha, d1_input, d2_input );
// copy the result back to the host
std::vector<float> device_result(num_elements);
cudaMemcpy(&device_result[0], d2_input, sizeof(float) * num_elements, cudaMemcpyDeviceToHost);
for (std::vector<float>::iterator it = device_result.begin() ; it != device_result.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
cudaFree(d1_input);
cudaFree(d2_input);
h1_input.clear();
h2_input.clear();
device_result.clear();
std::cout << "DONE! \n";
getchar();
return 0;
}
GPUメモリアクセスを理解しようとしています。簡単にするために、カーネルはAddloop<<<1,3>>>として起動されます。インスタンスとして gpu で動作する for ループを想像して、このコードがどのように機能するかを理解しようとしています。より具体的には、次の例を想像しますが、役に立ちません。
インスタンス 1:
for( i = 0; i < N; i += 3*1 ) // ( i += 0*1 --> i += 3*1 after Eric's comment)
y[i] = alpha*x[i] + y[i];
インスタンス 2:
for( i = 1; i < N; i += 3*1 )
y[i] = alpha*x[i] + y[i];
インスタンス 3:
for( i = 3; i < N; i += 3*1 )
y[i] = alpha*x[i] + y[i];
すべてのループの内部を見ると、2 つのベクトルを加算するロジックでは意味がありません。誰かが助けることができますか?
このインスタンスのロジックを採用している理由は、コメント内のカーネル内のコードの場合にうまく機能するためです。
これらの考えが正しければ、グリッド内に複数のブロックがある場合、インスタンスは何になるでしょうか? 言い換えれば、いくつかの例で は、i
値と更新レート ( ) はどうなるでしょうか?+=updaterate
PS:カーネル コードはhereから借用しました。
アップデート:
エリックの答えの後N = 15
、要素の数 ei の実行は次のようになると思います(間違っている場合は修正してください):
上記のインスタンス 1i = 0 , 3, 6, 9, 12
では、対応するy[i]
値が計算されます。上記のインスタンス 2i = 1 , 4, 7, 10, 13
については、対応する残りのy[i]
値を計算します。上記のインスタンス 3i = 2 , 5, 8, 11, 14
では、残りのy[i]
値が計算されます。