別の空のカーネルを呼び出すカーネルがあります。ただし、呼び出し元のカーネルが cudaDeviceSynchronize() を呼び出すと、カーネルがクラッシュし、実行がホストに直接送られます。メモリ チェッカーは、メモリ アクセスの問題を報告しません。そのような非文明的な行動の理由を知っている人はいますか?
クラッシュは、デバッガーからコードを実行した場合にのみ発生するようです(Visual Studio -> Nsight -> CUDA デバッグの開始)。コードを実行するたびにクラッシュが発生するわけではありません。クラッシュすることもあれば、問題なく終了することもあります。
問題を再現するための完全なコードは次のとおりです。
#include <cuda_runtime.h>
#include <curand_kernel.h>
#include "device_launch_parameters.h"
#include <stdio.h>
#define CUDA_RUN(x_, err_) {cudaStatus = x_; if (cudaStatus != cudaSuccess) {fprintf(stderr, err_ " %d - %s\n", cudaStatus, cudaGetErrorString(cudaStatus)); int k; scanf("%d", &k); goto Error;}}
struct computationalStorage {
float rotMat;
};
__global__ void drawThetaFromDistribution() {}
__global__ void chainKernel() {
computationalStorage* c = (computationalStorage*)malloc(sizeof(computationalStorage));
if (!c) printf("malloc error\n");
c->rotMat = 1.0f;
int n = 1;
while (n < 1000) {
cudaError_t err;
drawThetaFromDistribution<<<1, 1>>>();
if ((err = cudaGetLastError()) != cudaSuccess)
printf("drawThetaFromDistribution Sync kernel error: %s\n", cudaGetErrorString(err));
printf("0");
if ((err = cudaDeviceSynchronize()) != cudaSuccess)
printf("drawThetaFromDistribution Async kernel error: %s\n", cudaGetErrorString(err));
printf("1\n");
++n;
}
free(c);
}
int main() {
cudaError_t cudaStatus;
// Choose which GPU to run on, change this on a multi-GPU system.
CUDA_RUN(cudaSetDevice(0), "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
// Set to use on chip memory 16KB for shared, 48KB for L1
CUDA_RUN(cudaDeviceSetCacheConfig ( cudaFuncCachePreferL1 ), "Can't set CUDA to use on chip memory for L1");
// Set a large heap
CUDA_RUN(cudaDeviceSetLimit(cudaLimitMallocHeapSize, 1024 * 10 * 192), "Can't set the Heap size");
chainKernel<<<10, 192>>>();
cudaStatus = cudaDeviceSynchronize();
if (cudaStatus != cudaSuccess) {
printf("Something was wrong! Error code: %d", cudaStatus);
}
CUDA_RUN(cudaDeviceReset(), "cudaDeviceReset failed!");
Error:
int k;
scanf("%d",&k);
return 0;
}
すべてがうまくいけば、次のことが期待できます。
00000000000000000000000....0000000000000001
1
1
1
1
....
これは、すべてが正常に機能したときに得られるものです。ただし、クラッシュした場合:
000000000000....0000000000000Something was wrong! Error code: 30
ご覧のとおり、ステートメントerr = cudaDeviceSynchronize();
は終了せず、実行はホストに直接送られcudaDeviceSynchronize();
ますが、不明なエラー コード (30 = cudaErrorUnknown) で失敗します。
システム: CUDA 5.5、NVidia-Titan(ヘッドレス)、Windows 7x64、Win32 アプリケーション。更新: ディスプレイを駆動する追加の Nvidia カード、Nsight 3.2.0.13289。