質問

しているアプリケーションを通じて250MBのデータを簡易-迅速神経-純閾値機能のデータチャンク(2 32ビットの言葉を入れています。結果に基づき、非常に単純な計算には、チャンクはunpredictably押しの64箱に入っています。この大きな流れの中で、64(可変長)の流れです。

この繰り返し多くの異なる検出機能

の計算は、メモリ帯域幅の限定される。ただことがありません速度を変更しても利用判別機能するのかを計算機集約的である。

には、どうするのがベストな構造に書き込みの流れ最適メモリー帯域幅? 私は特に思考する理解のキャッシュの使用およびキャッシュ線のサイズが果たす役割はかなり大きます。想像し、最悪の場合には私が私の64出力ストリームによる運悪く、多くの地図と同じキャッシュする。その時に書き込んで、次の64ビットのデータをストリームのCPUをフラッシュ出ュキャッシュのラインをメインメモリ負荷に適切なキャッシュする。それぞれの用途は64バイトの帯域幅...私の帯域幅の限定ださるようお願い致しますの浪費95%、メモリ帯域幅(この仮定の最悪の場合、まいます。

でもしてみを計測する効果も持ち合わせを設計ざいますので、ちょっとしたものとしない。るのは僕のものを追いかけにゴーストのボトルネックとなり、ハードウェアを最適化していた以上にやりやすか?

私が使っているのCore IIのx86プロセッサの場合は違います。

編集:こちらは一部の例のコードです。この流れを配列にコピー元の様々な出力配列のみを疑似ランダム.走行プログラムと同じものと異なる番号の先箱を異なるランタイムでも、同額の計算は、メモリに読み込みおよび書き込みを行った:

2出力ストリームに分類されます。13秒
8出力ストリームに分類されます。13秒
32出力ストリームに分類されます。19秒
128出力ストリームに分類されます。29秒
512出力ストリームに分類されます。47秒

の違いを利用512対2出力ストリームは4X,(しょう??) によるキャッシュライン立ち退きのオーバーヘッド。

#include <stdio.h>
#include <stdlib.h>
#include <ctime>

int main()
{
  const int size=1<<19;
  int streambits=3;
  int streamcount=1UL<<streambits; // # of output bins
  int *instore=(int *)malloc(size*sizeof(int));
  int **outstore=(int **)malloc(streamcount*sizeof(int *));
  int **out=(int **)malloc(streamcount*sizeof(int));
  unsigned int seed=0;

  for (int j=0; j<size; j++) instore[j]=j;

  for (int i=0; i< streamcount; ++i) 
    outstore[i]=(int *)malloc(size*sizeof(int));

  int startTime=time(NULL);
  for (int k=0; k<10000; k++) {
    for (int i=0; i<streamcount; i++) out[i]=outstore[i];
    int *in=instore;

    for (int j=0; j<size/2; j++) {
      seed=seed*0x1234567+0x7162521;
      int bin=seed>>(32-streambits); // pseudorandom destination bin
      *(out[bin]++)=*(in++);
      *(out[bin]++)=*(in++);
    }

  }
  int endTime=time(NULL);
  printf("Eval time=%ld\n", endTime-startTime);
}
役に立ちましたか?

解決

あなたは64個の出力ビンに書いているとおり、

、あなたは、多くの異なるメモリ位置を使用することがあります。ビンをランダムに、本質的に満たされている場合、それはあなたが時々同じキャッシュラインを共有couls 2つのビンを持っているだろうことを意味します。ない大きな問題。コア2 L1キャッシュは8ウェイ連想です。それはあなたが唯一の第九のキャッシュラインの問題を取得したいことを意味します。任意の時間(1読み出し/書き込み64)でちょうど65ライブメモリ参照では、8ウェイ連想でOKです。

L2キャッシュは明らかに12ウェイの連想(3/6メガバイトの合計が、そう12はその変数ではない)です。あなたはL1での衝突を持っていると思いますので、場合でも、チャンスはあなたがまだメインメモリを打っていないかなり良いです。

あなたがこれを好きではない場合は、

ただし、メモリ内のビンを再配置します。代わりにstroingの各ビン順次、それらをインターリーブ。ビン0の場合、店のチャンクオフセット0-63で0-15が、店チャンク16-31は、8192から8255を相殺しました。ビン1については、店舗のチャンクエトセトラオフセット64-127、で0-15。これは、ほんの数ビットシフトとマスクがかかりますが、結果はビンのペアが8本のキャッシュラインを共有することです。

この場合、あなたのコードをスピードアップするための別の可能な方法は、特にx64のモードでは、SSE4あります。あなたは16個のレジスタは、128ビットxは取得したい、とあなたはキャッシュ汚染を制限するための読み取り(MOVNTDQA)を最適化することができます。私はしかし、それは読み込み速度で多くのことを助けるのかはわからない - 私はCore2のプリフェッチャがこれをキャッチするために期待したいです。シーケンシャル整数を読むと、任意のプリフェッチャーはそれを最適化する必要があり、可能なアクセスの最もシンプルなものです。

他のヒント

あなたは各「チャンク」を識別するために、インラインメタデータを単一のストリームとしてあなたの出力ストリームを書くためのオプションを持っていますか?あなたが読むことをした場合は「チャンクを、」あなたが真剣に思い、元のデータに続いて、それは(1バイト)に属しストリームあなただけ書くと特定の出力ストリームに書き込むのではなく、その後、それをあなたのthreshhold機能を実行しますあなたのスラッシングを減らします。

私はあなたがこれらのデータを何度も処理しなければならないと述べているという事実を除いて、これを示唆しています。それぞれの連続した実行時に、あなたは次の8バイトで、そのビンのために行う必要があるものは何でも、その後ビン数(1バイト)を得るためにあなたの入力ストリームを読みます。

限り、このメカニズムのcacheing行動として、あなただけの2つのデータストリームを通じてスライドさせて、すべてが、最初のケースでは、あなたが読んでいる限り多くのデータを書き込んでいることから、ハードウェアはあなたのすべての助けを与えるだろうおそらく限り等のプリフェッチ、キャッシュラインの最適化、などを期待することができます。

あなたは、余分なバイトにあなたがあなたのデータを処理し、すべての時間を追加する必要がありました場合は、

、あなたの最悪の場合のキャッシュの動作は、平均的なケースです。あなたは、ストレージのヒットに余裕があれば、それは私の勝利のように思えます。

あなたが本当に必死取得する場合

ここではいくつかのアイデアをしている...

あなたは、ハードウェアのアップグレードを検討するかもしれません。あなたと少し似てアプリケーションをストリーミングするために、私はi7プロセッサーに変更することで、大きな速度向上を得たことがわかりました。また、AMDのプロセッサは、(私は最近、自分自身をそれらを使用していないが)、メモリが結合した仕事のためにおそらくコア2よりも優れています。

あなたは検討するかもしれないもう一つの解決策は、CUDAのような言語を使用したグラフィックスカード上で処理を行っています。グラフィックスカードは、非常に高いメモリ帯域幅を持つようにし、高速な浮動小数点演算を行うようにチューニングされています。ストレートフォワード最適化されていないC実装にCUDAコード相対ため5X 20Xの開発時間を費やすことを期待します。

あなたはメモリにファイルをマップするために探索することがあります。この方法では、カーネルはあなたのためのメモリ管理の世話をすることができます。カーネルは通常、ページキャッシュを処理するために最善の方法を知っています。 アプリケーションが複数のプラットフォーム上で実行する必要がある場合は、別のOSが異なる方法でメモリ管理を扱うように、これは、特にそうです。

//www.cs.wustl:

ACE( HTTPのようなフレームワークがあります。 EDU /〜シュミット/ ACE.html に)またはブースト( http://www.boost.org )は、プラットフォームに依存しない方法でメモリマッピングを行うコードを書くことができます。

実際の回答例えば、このような場合にはコードの最大数アプローチと時間です。るのにかかっていることが明らかです。すべての人の私にはできないその他の方法についてです。

例えば:存在しない場合であってもキャッシュを詰(出力ストリームマッピングと同一のキャッシュ線の場合には、書面サイズの整数では、サイズ=1<<19sizeof(int)=4,32ビット(を書いていて8MBのデータは、実際に読み8MBとして書き8MB.なおデータは通常のWB(WriteBack)メモリ上のx86プロセッサーに書き込み線すずにコピーをもうけ、データの読み込みます。

消すことができることは不要RFO読交通(a)WCメモリ(おそらくる痛みの設定)又は(b)を使用SSEストリーミング店舗、通称NT(時間)。MOVNT*-MOVNTQ,MOVNTPS。(MOVNTDQAストリーミングの負荷がより痛み。)

たりすることによって動くというこさんによるgoogling http://blogs.fau.de/hager/2008/09/04/a-case-for-the-non-temporal-store/

現在:MOVNTして出力することができますをWBのメモリがあるようなトイレのメモリ使用し、小さな番号の書cmbiningバッファ.実際の数により異なるプロセッサーモデル:が4月の最初のインテルのチップにおいて、P6(通称:Pentium Pro)がある。Ooof...ブルドーザーの4K WCC(組み合わせのキャッシュ)基本的には提供64書込みバッファー、 http://semiaccurate.com/forums/showthread.php?t=6145&page=40, が4クラシックトバッファ.が http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-optimization-manual.pdf というあprocessos6WCバッファは、8.とにかく...が気になります。通常は64.

があることができることを試み:の実施を書き組み合わせます。

a)書き込み単一の64(#ト)バッファのサイズ64B(キャッシュ回線サイズ)でしたが、やっ128や256B.もうこれらのバッファする経常WBます。アクセスできて通常の店舗がご利用頂ければMOVNT*,す。

これらのバッファがフルにコピーしてバーストのメモリ、ストリームかれます。使用MOVNT*ストリーミング。

この時点で *Nバイトに格納され、一時バッファー、打L1キャッシュ *64*64バイトを読み込みは一時バッファ *Nバイトを読み込みからの臨時バッファー、打L1ます。*Nに書き込み、書き込まれたバイト経由のストリーミング店-基本的に直進めます。

I e Nバイトのキャッシュヒットを読み+Nバイトのキャッシュヒットを書+Nバイトのキャッシュミス

に対し、Nバイトのキャッシュミ読+Nバイトのキャッシュに書きを読み込みます。

を削減Nバイトのキャッシュミ読む環境省以外の余分なオーバーヘッド。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top