0

別の空のカーネルを呼び出すカーネルがあります。ただし、呼び出し元のカーネルが 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。

4

1 に答える 1

1

その最後の事実は決定的なものだったかもしれません。使用している nsight VSE のバージョンや正確なマシン構成については言及していません (たとえば、マシンに他の GPU がある場合、ディスプレイを駆動しているのはどれですか? )。 nsight VSE を使用して、単一 GPU モードで動的並列処理アプリケーションをデバッグします。

現在の機能マトリックスは、シングル GPU の CDP デバッグがまだサポートされていないことも示唆しています。

おそらく、あなたのケースで考えられる回避策の1つは、別のGPUを追加してディスプレイを駆動し、Titanカードをヘッドレスにすることです(つまり、モニターを接続せず、WindowsデスクトップをそのGPUに拡張しないでください)。

cuda-memcheck を使用して、または使用せずにアプリケーションを実行しましたが、問題はないようです。

于 2013-11-06T18:32:23.747 に答える