最近、インテル®TBBスケーラブル・アロケータに関する問題が発生しました。基本的な使用パターンは、サイズN * sizeof(double)
のインテルCPU上のキャッシュ・アライメント・メモリ割り当て
- いくつかのベクターは、
- はランダムな整数
M
ようM >= N/2 && M <= N
を生成割り当てられ、次の通りです。 - 各ベクトルの最初の
M
要素がアクセスされます。 - 手順2.を1000回繰り返します。
M
は固定長のパフォーマンスをベンチマークしたくないためランダムに設定しました。代わりに、ある範囲の長さのベクトルにわたって平均的なパフォーマンスを得たいと思っています。
N
の値によってプログラムのパフォーマンスが大きく異なります。これは、私がテストしている機能が大きなN
のパフォーマンスを優先させるように設計されているため、珍しくありません。しかし、パフォーマンスとN
の関係をベンチマークしようとしたとき、N
が1016
から1017
に増加すると、ある点で2つのフォールドの差があることがわかりました。
私の最初の本能は、N = 1016
のパフォーマンスの低下は小さなベクトルサイズとは関係がなく、キャッシュを行うことがあるということです。ほとんどの場合、誤った共有があります。テイスティング下の関数は、SIMD命令を使用しますが、スタックメモリは使用しません。第1のベクトルから1つの32バイト要素を読み取り、計算後、第2(および第3)ベクトルに32バイトを書き込む。誤った共有が発生すると、おそらく数十サイクルが失われ、それはまさに私が観察しているパフォーマンスのペナルティです。いくつかのプロファイリングでこれが確認されます。
元々、AVX命令の場合、各ベクトルを32バイト境界に揃えました。この問題を解決するために、私はベクトルを64バイトの境界に揃えました。しかし、私はまだ同じパフォーマンスのペナルティを観察します。 128バイトで整列させると問題が解決します。
もう少し掘りました。インテル®TBBはcache_aligned_allocator
です。そのソースでは、メモリも128バイトで整列されます。
これは私が理解できないものです。私が間違っていなければ、最新のx86 CPUには64バイトのキャッシュラインがあります。 はこれを確認します。以下は、インテルTBBのソースには、128バイトのアライメントがコメントでマークされていた、また、私は機能をチェックするためにCPUIDを使って書いた小さなプログラムから抽出された使用中のCPUの基本的なキャッシュ情報、
Vendor GenuineIntel
Brand Intel(R) Core(TM) i7-4960HQ CPU @ 2.60GHz
====================================================================================================
Deterministic Cache Parameters (EAX = 0x04, ECX = 0x00)
----------------------------------------------------------------------------------------------------
Cache level 1 1 2 3 4
Cache type Data Instruction Unified Unified Unified
Cache size (byte) 32K 32K 256K 6M 128M
Maximum Proc sharing 2 2 2 16 16
Maximum Proc physical 8 8 8 8 8
Coherency line size (byte) 64 64 64 64 64
Physical line partitions 1 1 1 1 16
Ways of associative 8 8 8 12 16
Number of sets 64 64 512 8192 8192
Self initializing Yes Yes Yes Yes Yes
Fully associative No No No No No
Write-back invalidate No No No No No
Cache inclusiveness No No No Yes No
Complex cache indexing No No No Yes Yes
----------------------------------------------------------------------------------------------------
ですそれは下位互換性のためだと言った。
なぜ私の場合、64バイトの整列が不十分なのですか?
ありがとう:全8セットはウルリック・ドレパーによって幻想的な記事から>
を使用しているときにスパイクを示し、ここでグラフを画像化
<。これは私が知っていたものですが、もっとはっきりと説明しました。しかし、割り当てられたメモリのサイズを増やさずにこの競合を避ける方法はありますか?私は、ほとんどの場合、2つのベクトルが同じキャッシュラインを共有するのを避けるのに、63バイトの境界で整列することで十分であるという印象を受けました。代わりに、私は128バイトの整列が必要であることを観察した –
グラフとリンクありがとう。私はそれについて最初に読んでいます。 –
アラインメントは、ここでの問題であるset-associativesnesであり、ベクトルによって使用される合計メモリを意味するので重要ではありません。 – Surt