後のメモリ内のデータの破損は、このコードを見てください:クーダ:カーネルコール
#include <stdlib.h>
#include <stdio.h>
int N, L, I;
float * inputs;
float * temp;
// first kernel
__global__ void mulKernel (float * output, float * inputs)///, float * weights)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
output [idx] = inputs [idx] * 3;//weights [idx];
//weights [idx] = 4;
//__syncthreads();
}
//second kernel
__global__ void sumKernel (float * output, float * input)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
output [idx] = input[idx]*2;
__syncthreads();
}
void printVector (const float *p, const int N) {
for (int i=0; i<N; i++)
printf("%f\n",p[i]);
}
int main(int argc, char *argv[])
{
if(argc < 3)
printf("Usage: cuda <layers> <inputs>\n");
else
{
L = atoi(argv[1]);
N = atoi(argv[2]);
I = atoi(argv[2]);
inputs = (float*)malloc(I*sizeof(float));
float * weights = (float*)malloc(I*sizeof(float));
// and fill with some arbitrary values
for (int i=0; i<I; i++)
{
inputs[i] = 1;
}
for (int i=0; i<I; i++)
{
weights[i] = 1.5;
}
// allocate device memory
float * devInputs = NULL;
float * devTemp = NULL;
float * devWeights = NULL;
cudaMalloc ((void**)&devInputs, I*sizeof(float));
cudaMalloc ((void**)&devTemp, I*sizeof(float));
cudaMalloc ((void**)&devWeights, I*sizeof(float));
// set kernel launch configuration
dim3 threadsMul = dim3(512, 1);
int blocksCount = floor(I/threadsMul.x) + 1;
dim3 blocksMul = dim3(blocksCount, 1);
dim3 threadsSum = dim3(512, 1);
blocksCount = floor(I/threadsSum.x) + 1;
dim3 blocksSum = dim3(blocksCount, 1);
cudaMemcpy (devInputs, inputs, I*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy (devWeights, weights,I*sizeof(float), cudaMemcpyHostToDevice);
//kernels calling in this cycle
for(int j=0;j<L;j++)
{
// copying data to see that's ok
cudaMemcpy (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost);
// print it
printf("inputs:\n");
printVector (inputs, N);
printf("weights:\n");
printVector (weights, N);
printf("\n");
// running first kernel
mulKernel<<<blocksMul, threadsMul>>>(devTemp, devInputs);//, devWeights);
// copying and printing data. We can see thats array weights contains a wrong values
cudaMemcpy (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost);
printf("inputs:\n");
printVector (inputs, N);
printf("weights:\n");
printVector (weights, N);
printf("\n");
if(cudaDeviceSynchronize() == cudaSuccess)
printf("threads syncronized\n");
cudaMemcpy (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost);
printf("inputs:\n");
printVector (inputs, N);
printf("weights:\n");
printVector (weights, N);
printf("\n");
sumKernel<<<blocksSum, threadsSum>>>(devInputs, devTemp);
cudaMemcpy (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost);
printf("inputs:\n");
printVector (inputs, N);
printf("weights:\n");
printVector (weights, N);
printf("\n\n");
if(cudaDeviceSynchronize() == cudaSuccess)
printf("threads syncronized\n");
cudaMemcpy (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost);
printf("inputs:\n");
printVector (inputs, N);
printf("weights:\n");
printVector (weights, N);
printf("\n\n");
}
cudaMemcpy (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost);
cudaFree (devInputs );
cudaFree (devTemp );
cudaFree (devWeights );
printVector (inputs, N);
free(inputs);
free(weights);
}
return 0;
}
を、出力を見て。最初のカーネルを呼び出した後、devWeights配列はそのデータを失いました。しかし、それはどこにも使われていません。私はそれをメモリにコピーし、カーネル(それには影響しません)を実行し、ホストにコピーし直します。そして出力において、私はそれが変わったことが分かります。どうして?私は間違って何をしていますか?
主な機能では、サイクルが表示されます。その中で私は2つのカーネル、sumKernelとmulKernelを実行します。カーネルを走らせる前、同期後、同期後にスレッドをホストして印刷します。だから、私はカーネルを呼び出した後に間違ったデータを見る。コードのコメントを参照してください。
エラーは表示されません(cudaSuccessのみ)。
CUDAエラーはまったくチェックされません。エラーをチェックしないと、何かが間違っているかどうかは決して分かりません。 – harrism
カーネルのコールコードがなければ、私たちはちょうど推測することができます。どのように変わったのですか?正しい引数で正しい順序でカーネルを呼び出したことは確かですか? – djmj
「出力を見てください」と尋ねます。しかし、どのように見えるか、コードが何をするか(あるいは問題が発生したときに使用するコマンドライン引数の値)について何も説明していない。あなたのコードが何をすべきかを知っている他の人はどうやってその問題を特定するのに役立つのでしょうか?あるいは、問題を引き起こすためにコードをどのように実行するのかを教えてください。 – talonmies