1

DAXPY線形代数カーネルのタイミングを実行する必要があります。単純に、私は次のようなことを試してみたいと思います:

fill(X,operand_size);
fill(Y,operand_size);
double seconds = timer();
daxpy(alpha,X,Y,operand_size);
seconds = timer() - seconds;

必要に応じて、コード全体のリンクが最後にあります。

問題は、オペランド x と y を埋めるためのメモリ アクセスによって、それらがプロセッサ キャッシュに配置されることです。したがって、DAXPY 呼び出しでのメモリへのその後のアクセスは、実際の運用よりもはるかに高速です。

これを回避する 2 つの方法を比較します。最初の方法は、 clflush命令を使用してすべてのレベルのキャッシュからオペランドをフラッシュすることです。2 番目の方法は、オペランド エントリがキャッシュから「自然に」追い出されるまで、非常に大きな配列を読み取ることです。両方をテストしました。これは、サイズ 2048 のオペランドを使用した単一の DAXPY 呼び出しのランタイムです。

Without flush: time=2840 ns
With clflush: time=4090 ns
With copy flush: time=5919 ns

数秒後に行われた別の実行を次に示します。

Without flush: time=2717 ns
With clflush: time=4121 ns
With copy flush: time=4796 ns

予想どおり、フラッシュによって実行時間が長くなります。ただし、コピー フラッシュによって DAXPY ルーチンの実行時間が大幅に長くなる理由がわかりません。clflush 命令はすべてのキャッシュからオペランドを削除する必要があるため、clflush の時間は、他のキャッシュ フラッシュ手順の実行時間の上限となる必要があります。それだけでなく、(両方の方法で) フラッシュされたタイミングもかなり跳ね返ります (数百ナノ秒対、フラッシュされていない場合の 10 ナノ秒未満)。手動フラッシュが実行時に劇的な違いをもたらす理由を知っている人はいますか?

付録

すべてのタイミング ルーチンとフラッシュ ルーチンを含む完全なコードは次のとおりです (194 行)。

http://codepad.org/hNJpQxTv

これは私のgccバージョンです。コードは -O3 オプションでコンパイルされます。(私は知っています、それは古いです;私が構築しなければならないいくつかのソフトウェアは、新しいgccと互換性がありません)

組み込みの仕様を使用します。

Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5646.1~2/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5646) (dot 1)

Intel Xeon 5650 プロセッサを搭載した Mac OS X 10.6 を使用しています。

4

1 に答える 1

2

CPU が通常の読み取り (ベンチマーク中に頻繁に発生する) に対して実際に行うこと (の一部) の擬似コードは、次のようになります。

if( cache line is not in cache ) {
    if(cache is full) {
        find cache line to evict
        if( cache line to evict is in "modified" state ) {
            write cache line to evict to slower RAM
        }
        set cache line to "free"
    }
    fetch the cache line from slower RAM 
}
temp = extract whatever we're reading from the cache line

CLFLUSHキャッシュをフラッシュしていた場合は、キャッシュが空のままif(cache is full)になるため false になります。CLFUSH

キャッシュをフラッシュするためにコピーを使用した場合、if(cache is full)ブランチは true になり、if( cache line is modified )半分の時間でも true になります (キャッシュの半分にはコピー中に読み取ったデータが含まれ、残りの半分にはコピー中に書き込んだデータが含まれます)。これは、半分の時間でwrite cache line to evict to slower RAM.

write cache line to evict to RAM実行すると、RAM チップの帯域幅が消費され、 のパフォーマンスに影響しますfetch the cache line from slower RAM

于 2013-03-29T23:58:38.053 に答える