2016-04-29 10 views
1

GPU上でいくつかのものを並列に計算し、すべてのカーネル呼び出しの間に結果を表示したい。コードは次のようになります。cudaでループを実行したいユーザーがキャンセルするまでカーネル

void execute(){ 
    runthread = true; 
    float erg[128 * 2] = {}; 
    float *d_a, *d_b, *d_c, *d_erg; 
    size_t sizeErg = sizeof(float) * 2 * N; 
    size_t sizeAB = sizeof(float)*N; 
    float c[2] = { 1, 2 }; 
    gpuErrchk(cudaMalloc((void**)&d_a, sizeAB)); 
    gpuErrchk(cudaMalloc((void**)&d_b, sizeAB)); 
    gpuErrchk(cudaMalloc((void**)&d_c, sizeof(float) * 2)); 
    gpuErrchk(cudaMalloc((void**)&d_erg, sizeErg)); 

    gpuErrchk(cudaMemcpy(d_a, anode, sizeAB, cudaMemcpyHostToDevice)); 
    gpuErrchk(cudaMemcpy(d_b, kathode, sizeAB, cudaMemcpyHostToDevice)); 
    gpuErrchk(cudaMemcpy(d_c, c, 2 * sizeof(float), cudaMemcpyHostToDevice)); 


    float time = 0; 
    int i = 0; 
    while (runthread){ 
     kernel<<<(N * 2)/64, 64 >>>(d_a, d_b, d_c, d_erg, N); 
     cudaDeviceSynchronize(); 
     gpuErrchk(cudaMemcpy(erg, d_erg, sizeErg, cudaMemcpyDeviceToHost)); 

     float acc = 0; 
     for (int j = 0; j < N * 2; j++){ 
      acc += erg[j]; 
     } 
     std::cout << "Erg" << i << "=" << acc << std::endl; 
     std::cout << "Kernel Execution took" << time << "ms" << std::endl; 
     i++; 
    } 
    cudaFree(d_a); 
    cudaFree(d_b); 
    cudaFree(d_c); 
    cudaFree(d_erg); 
} 

この関数は、bool変数runthreadを持つクラスの一部です。私の考えは、新しいCPUスレッドを実行関数で開始する別のメンバー関数を呼び出して、ユーザーがrunthreads = falseを設定する別のメンバー関数を呼び出すまでメイン関数を待機することでした。したがって、スレッドは、次のカーネルが終了した後に終了します。 私はVisual Studioから常にエラーメッセージを受け取ります。今これが可能かどうか、またはCPUがGPUの実行を制御しているのかどうか疑問に思っていましたか? GPUとCPU上での並列実行に関して、マルチスレッド化で誰かが危機に瀕していますか?または、whileループでuserinputを探すだけでいいですか?

答えて

3

GPUでの実行はCPU上の実行に関して非同期です。待機操作以外にも、CPU上で処理を続けることができます。コンフィグレーションフラグにもよりますが、cudaSetDeviceFlagsを参照すると、ウェイト動作はCPUサイクルを使用するかどうかを決定します。

cudaDeviceScheduleSpin:デバイスからの結果を待っているときにCUDAを積極的に回転させるように指示します。これにより、デバイスの待機時に待ち時間が短縮されますが、CPUスレッドがCUDAスレッドと並行して処理を実行している場合、CPUスレッドのパフォーマンスが低下する可能性があります。

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 

#include <stdio.h> 

volatile int runthread ; 

__global__ void kernel() { } 

#include <Windows.h> 


int execute(void* p) 
{ 
    int count = 0 ; 
    while (runthread) 
    { 
     kernel<<<1,1>>>(); 
     cudaDeviceSynchronize(); 
     ++count; 
    } 
    printf ("Executed kernel %d times\n", count); 
    ::ExitThread(count); 
    return count ; 
} 

int main() 
{ 
    runthread = 1 ; 

    HANDLE hThread = ::CreateThread (0, 0, (LPTHREAD_START_ROUTINE)execute, 0, 0, 0) ; 

    printf ("Press key\n") ; 
    int c = getc(stdin); 

    printf ("Stopping\n") ; 

    runthread = 0 ; 

    ::WaitForSingleObject (hThread, INFINITE) ; 

    printf ("DONE\n"); 
    return 0 ; 
} 

は、しかし、あなたには、いくつかのCUDAの設定およびステータスの要素があるとして、CUDAの呼び出しを実行するスレッド上で、慎重になりたい:あなたが達成したい何

は(ここでは、Windows上の例)完全に実現可能ですスレッドごとに格納されます。別のスレッドからcudaを使用する場合は、thisの投稿をおすすめします。本質的には、cuCtxSetCurrent APIコールを使用してスレッドにcuda環境をアタッチする必要があります。最も簡単なのは、すべてのcudaコードを1つのスレッドで実行することです。