4

データ転送とカーネル実行をオーバーラップさせようとすると、使用するストリームに関係なく、カードがすべてのメモリ転送を順番に実行しているように見えます。

したがって、次を発行すると:

  • ストリーム 1: MemcpyA_HtoD_1; カーネル_1; MemcpyA_DtoH_1
  • ストリーム 2: MemcpyA_HtoD_2; カーネル_2; MemcpyA_DtoH_2

MemcpyA_HtoD_2 は MemcpyA_DtoH_1 が完了するまで待機します。したがって、オーバーラップは達成されません。使用するストリームの構成に関係なく、Memcpy 操作は常に順番に発行されます。したがって、オーバーラップを実現する唯一の方法は、出力をバッファリングするか、次の反復まで出力転送を遅らせることです。

CUDA 5.5、Windows 7 x64、および GTX Titan を使用しています。すべての CPU メモリが固定され、data_transfers は非同期バージョンを使用して行われます。

次の画面で動作を確認してください。

発行、host_to_device -> kernel -> device_to_host (通常の動作) となり、オーバーラップを取得できません。

非重複

host_to_device -> kernel (kernel の後に device_to_host を回避) を発行するとオーバーラップが発生します...どのようなストリーム構成を試しても、すべてのメモリ コピーが順番に実行されるためです。

重複

アップデート

誰かがこの問題を再現することに興味がある場合は、この望ましくない動作を示す合成プログラムをコーディングしました. CUDA 5.5 を使用した完全な VS2010 ソリューション

VS2010 ストリームが機能しない リンク

オーバーラップをテストするために誰かがこれを Linux で実行できますか?

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


#include <stdio.h>
#define N 1024*1024

__global__ void someKernel(int *d_in, int *d_out) {
    for (int i = threadIdx.x; i < threadIdx.x + 1024; i++) {
        d_out[i] = d_in[i];
    }
}

int main () {
    int *h_bufferIn[100];
    int *h_bufferOut[100];
    int *d_bufferIn[100];
    int *d_bufferOut[100];

    //allocate some memory
    for (int i = 0; i < 100; i++) {
        cudaMallocHost(&h_bufferIn[i],N*sizeof(int));
        cudaMallocHost(&h_bufferOut[i],N*sizeof(int));
        cudaMalloc(&d_bufferIn[i], N*sizeof(int));
        cudaMalloc(&d_bufferOut[i], N*sizeof(int));
    }

    //create cuda streams
    cudaStream_t st[2];
    cudaStreamCreate(&st[0]);
    cudaStreamCreate(&st[1]);

    //trying to overlap computation and memcpys
    for (int i = 0; i < 100; i+=2) {
        cudaMemcpyAsync(d_bufferIn[i], h_bufferIn[i], N*sizeof(int), cudaMemcpyHostToDevice, st[i%2]);
        someKernel<<<1,256, 0, st[i%2]>>>(d_bufferIn[i], d_bufferOut[i]);
        cudaMemcpyAsync(h_bufferOut[i], d_bufferOut[i], N*sizeof(int), cudaMemcpyDeviceToHost, st[i%2]);
        cudaStreamQuery(0);

        cudaMemcpyAsync(d_bufferIn[i+1], h_bufferIn[i+1], N*sizeof(int), cudaMemcpyHostToDevice, st[(i+1)%2]);
        someKernel<<<1,256, 0, st[(i+1)%2]>>>(d_bufferIn[i+1], d_bufferOut[i+1]);
        cudaMemcpyAsync(h_bufferOut[i+1], d_bufferOut[i+1], N*sizeof(int), cudaMemcpyDeviceToHost, st[(i+1)%2]);
        cudaStreamQuery(0);
    }
    cudaDeviceSynchronize();
}
4

1 に答える 1

1

TL;DR:この問題は、Nsight モニタの WDDM TDR 遅延オプションが原因です! false に設定すると、問題が発生します。代わりに、TDR 遅延値を非常に高い数値に設定し、「有効」オプションを true に設定すると、問題は解消されます。

上記の解決策にたどり着くまでの他の(古い)手順と、その他の考えられる原因については、以下をお読みください。

私は最近、この問題を部分的に解決することができました! それは窓とエアロに固有のものだと思います。これらの手順を試して、結果を投稿して他の人を助けてください! GTX 650 と GT 640 で試しました。

何かを行う前に、オンボード gpu (ディスプレイとして) とディスクリート gpu (計算用) の両方を使用することを検討してください。これは、Windows 用の nvidia ドライバーで問題が確認されているためです。オンボード GPU を使用すると、ドライバーが完全にロードされないため、多くのバグが回避されます。また、作業中もシステムの応答性を維持!

  1. 並行性の問題が、古いドライバー (BIOS を含む) などの他の問題に関連していないことを確認してください。
  2. コンピューター>プロパティに移動します
  3. 左側で高度なシステム設定を選択します
  4. 詳細タブに移動します
  5. オン パフォーマンス クリック設定
  6. [視覚効果] タブで、[最適なパフォーマンスに調整する] を選択します。

これにより、エアロとほぼすべての視覚効果が無効になります。この構成が機能する場合は、問題を引き起こしている正確なボックスが見つかるまで、視覚効果用のボックスを 1 つずつ有効にしてみてください。

または、次のこともできます。

  1. デスクトップを右クリックし、パーソナライズを選択します
  2. 基本テーマの中からエアロのないテーマを選びます。

これも上記と同じように機能しますが、より多くの視覚オプションが有効になっています。私の 2 つのデバイスでは、この設定も機能するので、そのままにしておきます。

これらの解決策を試すときは、ここに戻って結果を投稿してください。

私にとっては、ほとんどの場合(私が作成したタイル張りのdgemm)の問題を解決しましたが、まだ「simpleStreams」を適切に実行して同時実行を達成できないことに注意してください...

更新:この問題は、新しい Windows インストールで完全に解決されました!! 前の手順で一部のケースの動作が改善されましたが、すべての問題を解決したのは新規インストールだけでした!

この問題を解決するための根本的ではない方法を見つけようとします。レジストリだけを復元するだけで十分かもしれません。

于 2015-04-21T14:21:42.233 に答える