2011-08-05 11 views
4

私のコード(マルチGPU、同じGPU上の同時カーネル、カーネルの順次実行などを含む)の異なる部分(cudaMemcpyHtoD、カーネル実行、cudaMemcpyDtoH) al)。私が理解しているように、これらの関数はイベント間の経過時間を記録しますが、コードの寿命に沿ってイベントを挿入すると、オーバーヘッドや不正確な結果になることがあります。私はこれらの機能を改善するための批判や一般的なアドバイスを聞きたいと思います。イベントを使用したCUDAアプリケーションのタイミングタイミング

//Create event and start recording 
cudaEvent_t *start_event(int device, cudaEvent_t *events, cudaStream_t streamid=0) 
{ 
     cutilSafeCall(cudaSetDevice(device)); 
     cutilSafeCall(cudaEventCreate(&events[0])); 
     cutilSafeCall(cudaEventCreate(&events[1])); 
     cudaEventRecord(events[0], streamid); 

    return events; 
} 

//Return elapsed time and destroy events 
float end_event(int device, cudaEvent_t *events, cudaStream_t streamid=0) 
{ 

     float elapsed = 0.0; 
     cutilSafeCall(cudaSetDevice(device)); 
     cutilSafeCall(cudaEventRecord(events[1], streamid)); 
     cutilSafeCall(cudaEventSynchronize(events[1])); 
     cutilSafeCall(cudaEventElapsedTime(&elapsed, events[0], events[1])); 

     cutilSafeCall(cudaEventDestroy(events[0])); 
     cutilSafeCall(cudaEventDestroy(events[1])); 

     return elapsed; 
} 

使用方法:これは、生産コードのためであれば

cudaEvent_t *events; 
cudaEvent_t event[2]; //0 for start and 1 for end 
... 
events = start_event(cuda_device, event, 0); 
<Code to time> 
printf("Time taken for the above code... - %f secs\n\n", (end_event(cuda_device, events, 0)/1000)); 

答えて

9

まず、あなたは)二cudaEventRecordとcudaEventSynchronize(間に何かをできるようにしたいことがあります。そうしないと、GPUとCPUの動作をオーバーラップさせるアプリの能力が低下する可能性があります。

次に、イベントの作成と破壊をイベント記録と区別します。私はコストはわかりませんが、一般的にはcudaEventCreateとcudaEventDestroyを頻繁に呼びたくないかもしれません。それを作るために、このクラスを使用するコードに委ねられるべきもの私には思える - 私はどうなるのか

は、私はcudaSetDeviceを()含まれていませんでした。この

class EventTimer { 
public: 
    EventTimer() : mStarted(false), mStopped(false) { 
    cudaEventCreate(&mStart); 
    cudaEventCreate(&mStop); 
    } 
    ~EventTimer() { 
    cudaEventDestroy(mStart); 
    cudaEventDestroy(mStop); 
    } 
    void start(cudaStream_t s = 0) { cudaEventRecord(mStart, s); 
            mStarted = true; mStopped = false; } 
    void stop(cudaStream_t s = 0) { assert(mStarted); 
            cudaEventRecord(mStop, s); 
            mStarted = false; mStopped = true; } 
    float elapsed() { 
    assert(mStopped); 
    if (!mStopped) return 0; 
    cudaEventSynchronize(mStop); 
    float elapsed = 0; 
    cudaEventElapsedTime(&elapsed, mStart, mStop); 
    return elapsed; 
    } 

private: 
    bool mStarted, mStopped; 
    cudaEvent_t mStart, mStop; 
}; 

注のようなクラスを作成していますより柔軟なユーザーは、起動と停止が呼び出されたときに、同じデバイスがアクティブであることを確認する必要があります。

PS:製品コードのために依拠するCUTILのためのNVIDIAの意図ではない - それが私たちの例では便宜上、単に使用され、など厳密CUDAライブラリやコンパイラ自身として試験または最適化されていません。私はあなたのライブラリとヘッダにcutilSafeCall()のようなものを抽出することをお勧めします。

関連する問題