CUDA:CUDAの理解
4866 ワード
1.GPUの理解演算能力を向上させるために、「より多くの、簡単な計算ユニット」 を使うのが好きです. CPUが解決した問題はLatencyであり、各タスクは最短でどのくらいの時間で を完成できるかである. GPUはThroughPutを解決して、1単位の時間ごとにどれだけの任務を解決することができます GPUは効率的な同時 を得意とする並列実行大量スレッド 2.CUDA計算モデル3.典型的なGPUプログラム CPUはGPUにメモリ空間CUDA MALLOC を割り当てる. CPUコピー入力データCPU->GPU CUDA memcpy CPU launches kernel on GPUデータkernel Launch を計算する CPUはコピー要求を送信し、GPU->CPU CUDA memcpy 上記の2,4ステップはいずれもデータの転送であり,いずれも非常に高価である.
4. BIG IDEA
Kernels look serial programs.Write your program as if it will run on one thread.The GPU will run that program on many threads
5.最も簡単なCUDAプログラム
これは1組の数字の平方を計算するCUDAプログラムです.global__修飾子はCUDA関数でありkernel functionとも呼ばれる.
全体のプログラムは簡単で分かりやすくて、注釈ははっきりしていて、あまり説明しません
6.BLOCKとGRID多くのスレッドがBLOCKに整理され、threadIdx変数はスレッドがどのスレッドであるかを示します.一方、BLOCKには、1つのBLOCKが最大1024スレッドを含むことができるという制限があります.どうすればいいですか.私たちは複数のBLOCKを使って、複数のBLOCKをどのように組織することができますか.GRIDを使用! GRIDとBLOCKの関係はBLOCKとTHREADの関係と類似している. BLOCKおよびGRIDはintタイプであってもよいしdim 3タイプ であってもよい <<<...>>> シンボルは、BLOCKおよびGRID の使用量を指定する BLOCKは、1次元、2次元、3次元の であることができる. kernelはblockIdx変数によって現在そのBLOCK を取得する. BLOCKの次元数はblockDimという変数によって を得ることができる.組織構造図 Memory
1)Local memory:スレッド内の変数が占めるメモリ
2)shared memory:1つのBLOCK内部のすべてのスレッドが共有するメモリ【注意:_shared__修飾子はこのBLOCK共有メモリを表す】
3)global memory:全スレッド共有メモリ
速度1)2より大きい)3よりはるかに大きい)
ここに練習問題があります:次のこのコード、1,2,3,4行の中で、各行の演算が最も速くて、どの行が最も遅くて、それぞれ各行に点数をつけて、点数は1~4です
同期(Synchronise)
コードに障害を設けるように
次に、array[x]=array[x+1]を前に移動したい配列があります.
簡単な関数フレームワークは次のようになります.
array[20] = 20;実行可能
array[20] = array[20+1];スレッド21がスレッド20の後に実行される場合、この文の付与は間違いであることは明らかである.
では、上記のプログラムを正しく実行するには、コードにいくつかの「障害」を設定する必要があります.
4. BIG IDEA
Kernels look serial programs.Write your program as if it will run on one thread.The GPU will run that program on many threads
5.最も簡単なCUDAプログラム
これは1組の数字の平方を計算するCUDAプログラムです.global__修飾子はCUDA関数でありkernel functionとも呼ばれる.
全体のプログラムは簡単で分かりやすくて、注釈ははっきりしていて、あまり説明しません
#include <stdio.h>
__global__ void square(float * d_out, float * d_in)
{
int idx = threadIdx.x;
float f = d_in[idx];
d_out[idx] = f * f;
}
int main(int argc, char ** argv)
{
const int ARRAY_SIZE = 64;
const int ARRAY_BYTES = ARRAY_SIZE * sizeof(float);
// generate the input array on the host
float h_in[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++)
{
h_in[i] = float(i);
}
float h_out[ARRAY_SIZE];
// declare GPU memory pointers
float *d_in;
float *d_out;
// allocate GPU memory
cudaMalloc((void**) &d_in, ARRAY_BYTES);
cudaMalloc((void**) &d_out, ARRAY_BYTES);
// transfer the array to the GPU
cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);
// launch the kernel
square<<<1, ARRAY_SIZE>>>(d_out, d_in);
// copy back the result array to the CPU
cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);
// print out the resulting array
for (int i =0; i < ARRAY_SIZE; i++) {
printf("%f", h_out[i]);
printf(((i % 4) != 3) ? "\t" : "
");
}
cudaFree(d_in);
cudaFree(d_out);
return 0;
}
6.BLOCKとGRID
1)Local memory:スレッド内の変数が占めるメモリ
2)shared memory:1つのBLOCK内部のすべてのスレッドが共有するメモリ【注意:_shared__修飾子はこのBLOCK共有メモリを表す】
3)global memory:全スレッド共有メモリ
速度1)2より大きい)3よりはるかに大きい)
ここに練習問題があります:次のこのコード、1,2,3,4行の中で、各行の演算が最も速くて、どの行が最も遅くて、それぞれ各行に点数をつけて、点数は1~4です
__global__ void foo(float *x,float *y,float *z)
{
__shared__ float a,b,c;
float s,t,u;
s = *x;//1
t = s;//2
a = b;//3
*y = *z;//4
}
__global__ void foo(float *x,float *y,float *z){
__shared__ float a,b,c;
float s,t,u;
s = *x;//1
t = s;//2
a = b;//3
*y = *z;//4
}
答えは:これによって1の速度は3で、2行の速度は1で、3は2で、4は4です同期(Synchronise)
コードに障害を設けるように
次に、array[x]=array[x+1]を前に移動したい配列があります.
簡単な関数フレームワークは次のようになります.
__global__ void shift(){
int idx = threadIdx.x;
__shared__ int array[128];
array[idx] = threadIdx.x;
if (idx < 127) {
array[idx] = array[idx + 1];
}
}
__global__ void shift(){
int idx = threadIdx.x;
__shared__ int array[128];
array[idx] = threadIdx.x;
if (idx < 127) {
array[idx] = array[idx + 1];
}
}
並行実行を少し理解すると、上記のコードがうまく実行できないことがわかります.例えば、スレッド20が実行する場合、array[20] = 20;実行可能
array[20] = array[20+1];スレッド21がスレッド20の後に実行される場合、この文の付与は間違いであることは明らかである.
では、上記のプログラムを正しく実行するには、コードにいくつかの「障害」を設定する必要があります.
__global__ void shift(){
int idx = threadIdx.x;
__shared__ int array[128];
array[idx] = threadIdx.x;
__syncthreads();// ,
if (idx < 127) {
int temp = array[idx + 1];
__syncthreads();// barrier, , ,
array[idx] = temp;
__syncthreads();// array
}
}
__global__ void shift(){
int idx = threadIdx.x;
__shared__ int array[128];
array[idx] = threadIdx.x;
__syncthreads();// ,
if (idx < 127) {
int temp = array[idx + 1];
__syncthreads();// barrier, , ,
array[idx] = temp;
__syncthreads();// array
}
}