私はCUDAの初心者で、推力のチュートリアルを読んでいます。単純ですが、ひどく整理されたコードを書いて、推力の加速を理解しようとしています(このアイデアは正しいですか?)。cpuに配列を追加し、gpuにdevice_vectorを追加して、2つのベクトル(10000000 int)を別のベクトルに追加しようとしています。
これがそのことです:
#include <iostream>
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#define N 10000000
int main(void)
{
float time_cpu;
float time_gpu;
int *a = new int[N];
int *b = new int[N];
int *c = new int[N];
for(int i=0;i<N;i++)
{
a[i]=i;
b[i]=i*i;
}
clock_t start_cpu,stop_cpu;
start_cpu=clock();
for(int i=0;i<N;i++)
{
c[i]=a[i]+b[i];
}
stop_cpu=clock();
time_cpu=(double)(stop_cpu-start_cpu)/CLOCKS_PER_SEC*1000;
std::cout<<"Time to generate (CPU):"<<time_cpu<<std::endl;
thrust::device_vector<int> X(N);
thrust::device_vector<int> Y(N);
thrust::device_vector<int> Z(N);
for(int i=0;i<N;i++)
{
X[i]=i;
Y[i]=i*i;
}
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);
thrust::transform(X.begin(), X.end(),
Y.begin(),
Z.begin(),
thrust::plus<int>());
cudaEventRecord(stop,0);
cudaEventSynchronize(stop);
float elapsedTime;
cudaEventElapsedTime(&elapsedTime,start,stop);
std::cout<<"Time to generate (thrust):"<<elapsedTime<<std::endl;
cudaEventDestroy(start);
cudaEventDestroy(stop);
getchar();
return 0;
}
CPUの結果は非常に高速に見えますが、私のマシン(i5-2320,4G、GTX 560 Ti)ではGPUの実行速度が非常に遅く、CPU時間は約26、GPU時間は約30です。私は自分のコードの愚かなエラーで推力を間違っただけでしたか?それとももっと深い理由がありましたか?
C ++の新人として、コードを何度もチェックしましたが、GPUで推力を使用すると時間が遅くなりました。そこで、5つの異なるアプローチでvectorAddを計算することの違いを示すためにいくつかの実験を行いました。QueryPerformanceFrequency()
統一された時間測定方法としてWindowsAPIを使用しています。
各実験は次のようになります。
f = large_interger.QuadPart;
QueryPerformanceCounter(&large_interger);
c1 = large_interger.QuadPart;
for(int j=0;j<10;j++)
{
for(int i=0;i<N;i++)//CPU array adding
{
c[i]=a[i]+b[i];
}
}
QueryPerformanceCounter(&large_interger);
c2 = large_interger.QuadPart;
printf("Time to generate (CPU array adding) %lf ms\n", (c2 - c1) * 1000 / f);
__global__
これがGPU配列を追加するための私の単純な関数です:
__global__ void add(int *a, int *b, int *c)
{
int tid=threadIdx.x+blockIdx.x*blockDim.x;
while(tid<N)
{
c[tid]=a[tid]+b[tid];
tid+=blockDim.x*gridDim.x;
}
}
関数は次のように呼び出されます。
for(int j=0;j<10;j++)
{
add<<<(N+127)/128,128>>>(dev_a,dev_b,dev_c);//GPU array adding
}
ベクトルa[N]とb[N]をベクトルc[N]に追加して、次のように10回ループします。
- CPUにアレイを追加
- CPUにstd::vectorを追加します
- CPUにthrust::host_vectorを追加します
- GPUにthrust::device_vectorを追加します
- GPUにアレイを追加します。これが結果です
N=10000000の場合
そして私は結果を得る:
- 268.992968msを追加するCPUアレイ
- CPU std::vector追加1908.013595ms
- CPU Thrust::host_vectorが10776.456803msを追加
- GPU Thrust::device_vectorが297.156610msを追加
- 5.210573msを追加するGPUアレイ
そして、これは私を混乱させました、私はテンプレートライブラリの実装に精通していません。コンテナと生データ構造の間でパフォーマンスは本当に大きく異なりましたか?