11

一度だけ使用cudaMemcpy()して、正確に1GBのデータをデバイスにコピーします。これには5.9秒かかります。逆に、5.1秒かかります。これは正常ですか?
関数自体には、コピーする前に非常に多くのオーバーヘッドがありますか?理論的には、PCIeバスのスループットは少なくとも4GB/秒である必要があります。
Tesla C870はそれをサポートしていないため、重複するメモリ転送はありません。ヒントはありますか?

編集2:私のテストプログラム+更新されたタイミング; 読みすぎないように!
関数がコンパイルされcutCreateTimer()ません:'エラー:識別子 "cutCreateTimer"が未定義です'-これは、マシンにインストールされている古いcudaバージョン(2.0)に関連している可能性があります

 __host__ void time_int(int print){
static struct timeval t1; /* var for previous time stamp */
static struct timeval t2; /* var of current time stamp */
double time;
if(gettimeofday(&t2, 0) == -1) return;
if(print != 0){
  time = (double) (t2.tv_sec - t1.tv_sec) + ((double) (t2.tv_usec - t1.tv_usec)) / 1000000.0;
  printf(...);
}
t1 = t2;
}

main:
time(0);
void *x;
cudaMallocHost(&x,1073741824);
void *y;
cudaMalloc(&y, 1073741824);
time(1);
cudaMemcpy(y,x,1073741824, cudaMemcpyHostToDevice);
time(1);
cudaMemcpy(x,y,1073741824, cudaMemcpyDeviceToHost);
time(1);

表示されるタイミングは次のとおりです。0.86
秒の割り当て
0.197秒の最初のコピー
5.02秒の2番目のコピー
奇妙なことに、最初のコピーでは0.197秒と表示されますが、プログラムの実行を見るとはるかに時間がかかります。

4

3 に答える 3

12

はい、これは正常です。cudaMemcpy()多くのチェックと動作を行います (ホスト メモリが通常またはによって割り当てられた場合)。データのすべてのページがメモリ内にあることを確認し、ページを (1 つずつ) ドライバーに移動する必要があります。malloc()mmap()

cudaHostAllocの代わりに、関数またはを使用cudaMallocHostしてメモリを割り当てることができますmalloc。常に RAM に格納され、GPU の DMA から直接 (より高速に) アクセスできる固定メモリを割り当てますcudaMemcpy()。最初のリンクからの引用:

ページ ロックされ、デバイスからアクセス可能なホスト メモリの count バイトを割り当てます。ドライバーは、この関数で割り当てられた仮想メモリ範囲を追跡し、cudaMemcpy() などの関数の呼び出しを自動的に高速化します。

唯一の制限要因は、システム内の固定メモリの合計量が制限されRAMていることです (サイズを超えないでください。使用することをお勧めしますRAM - 1Gb):

大量の固定メモリーを割り当てると、システムがページングに使用できるメモリーの量が減少するため、システムのパフォーマンスが低下する可能性があります。そのため、この関数は、ホストとデバイス間のデータ交換用のステージング領域を割り当てるために控えめに使用するのが最適です。

于 2011-09-15T11:35:13.400 に答える
6

転送のタイミングが正確であると仮定すると、固定メモリからの 1 GB の転送で 1.1 秒は遅いように見えます。PCIe スロットが正しい幅に構成されていますか? 完全なパフォーマンスを得るには、x16 構成が必要です。一部のプラットフォームには 2 つのスロットがあり、そのうちの 1 つは x16 として構成され、もう 1 つは x4 として構成されます。そのため、マシンにスロットが 2 つある場合は、カードを別のスロットに移動してみてください。他のシステムには 2 つのスロットがあり、1 つのスロットのみが占有されている場合は x16 を取得しますが、両方が占有されている場合は x8 の 2 つのスロットを取得します。BIOS セットアップは、PCIe スロットがどのように構成されているかを理解するのに役立つ場合があります。

Tesla C870 はかなり古いテクノロジーですが、私の記憶が正しければ、第 1 世代の PCIe インターフェイスを使用したこれらのパーツを使用すると、固定メモリから約 2 GB/秒の転送速度が可能になるはずです。現在の Fermi クラスの GPU は PCIe gen 2 インターフェイスを使用し、固定メモリからの転送で 5 GB/秒以上を達成できます (スループット測定の場合、1 GB/秒 = 10^9 バイト/秒)。

PCIe はパケット化されたトランスポートを使用し、一般的なチップセットがサポートするパケット サイズではパケット オーバーヘッドが大きくなる可能性があることに注意してください。新しいチップセットは通常、やや長いパケットをサポートします。固定されたホストメモリとの間の転送であっても、方向ごとの公称最大値 (PCIe 1.0 x16 の場合は 4 GB/秒、PCIe 2.0 x16 の場合は 8 GB/秒) の 70% を超えることはほとんどありません。以下は、オーバーヘッドの問題を説明するホワイト ペーパーであり、さまざまなパケット サイズで達成可能な使用率を示す便利なグラフがあります。

http://www.plxtech.com/files/pdf/technical/expresslane/Choosing_PCIe_Packet_Payload_Size.pdf

于 2011-09-15T18:00:00.283 に答える
1

適切に構成されていないシステム以外に、ひどい PCIe 帯域幅の最も良い説明は、IOH/ソケットと、GPU が差し込まれている PCIe スロットとの間のミスマッチです。

ほとんどのマルチソケット Intel i7 クラス (Nehalem、Westmere) マザーボードには、ソケットごとに 1 つの I/O ハブがあります。システム メモリは各 CPU に直接接続されているため、「ローカル」の DMA アクセス (DMA アクセスを行う GPU と同じ IOH に接続された CPU からメモリをフェッチする) は、非ローカルのもの (接続された CPU からメモリをフェッチする) よりもはるかに高速です。 2 つの CPU をリンクする QPI インターコネクトを介して満たす必要があるトランザクション)。

重要な注意: 残念ながら、SBIOS がインターリーブ用にシステムを構成するのは一般的です。これにより、連続したメモリ割り当てがソケット間でインターリーブされます。これにより、CPU のローカル/非ローカル アクセスによるパフォーマンスの低下が軽減されますが (考えられる 1 つの方法: すべてのメモリ アクセスが両方のソケットで等しく悪くなります)、データへの GPU アクセスに大混乱が生じます。 - ソケット システムを非ローカルにします。

システムに IOH が 1 つしかない場合、Nehalem および Westmere クラスのシステムはこの問題に悩まされることはないようです。

(ちなみに、Sandy Bridge クラスのプロセッサは、PCI Express サポートを CPU に統合することで、この道をさらに一歩進んでいます。そのため、Sandy Bridge を使用すると、マルチソケット マシンは自動的に複数の IOH を持ちます。)

この仮説を調べるには、テストをソケットに固定するツール (利用可能な場合は Linux の numactl) を使用してテストを実行するか、プラットフォーム依存のコードを使用して特定のソケットで実行するように割り当てとスレッドを操作します。凝らなくても多くのことを学ぶことができます - main() の先頭でグローバル効果を持つ関数を呼び出して、すべてを強制的にいずれかのソケットに配置し、それが PCIe 転送パフォーマンスに大きな影響を与えるかどうかを確認してください。

于 2011-09-16T12:47:17.377 に答える