上記のポスターで述べたように、make_sharedを使用してオブジェクトを作成すると、参照されるオブジェクトに隣接する「制御ブロック」が作成されます。
しかしあなたの場合、これは悪い選択だと思います。
メモリを割り当てる場合、大きなブロックであっても、まばらで断片化されたページ割り当てとは対照的に、連続した「物理スペース」を取得する保証はありません。このため、リストを反復処理すると、制御構造(データを指す)を取得するためだけに、メモリの広いスパンにわたって読み取りが発生します。
「しかし、私のキャッシュラインは64バイトの長さです!」あなたは言う。これが当てはまる場合、 「これは、オブジェクトが制御構造とともにキャッシュにロードされることを意味します」と思うかもしれませんが、必ずしもそうとは限りません。これは、データアライメント、キャッシュラインサイズ、キャッシュの関連付け、実際に使用するメモリ帯域幅など、さまざまな要因によって異なります。
あなたが遭遇する問題は、データがどこにあるかを把握するために最初に制御構造をフェッチする必要があるという事実です。代わりに、それはすでにキャッシュに存在する可能性があるため、データの一部(制御構造)は少なくともmake_sharedを使用する代わりに、それらをすべて一緒に割り当てると、実質的にキャッシュ内にあることが保証されます。
データをキャッシュに適したものにしたい場合は、データへのすべての参照が可能な限り最高レベルのキャッシュ内に収まるようにする必要があります。引き続き使用すると、キャッシュにとどまるようにするのに役立ちます。キャッシュアルゴリズムは、コードが非常にブランチが多い場合を除いて、データのフェッチを処理するのに十分なほど洗練されています。これは、データを「キャッシュフレンドリー」にするためのもう1つの部分です。データを操作するときは、使用するブランチをできるだけ少なくします。
また、作業するときは、キャッシュに収まるように分割してください。可能であれば、一度に32kでのみ動作します。これは、最新のプロセッサでは控えめな数値です。コードを実行するCPUが正確にわかっている場合は、必要に応じて、それほど保守的に最適化することはできません。
編集:私は適切な詳細に言及するのを忘れました。最も頻繁に割り当てられるページサイズは4kです。特にローエンドプロセッサでは、キャッシュは「連想的」であることがよくあります。2ウェイアソシアティブとは、メモリ内の各場所を他のすべてのキャッシュエントリにのみマップできることを意味します。4ウェイアソシアティブは、4つの可能なマッピングのいずれかに適合できることを意味し、8ウェイは、8つの可能なマッピングのいずれかに適合できることを意味します。プロセッサ上の最速のキャッシュ(L1)は、必要な制御ロジックが少ないため、関連付けが最も少なくなる傾向があります。参照するデータの連続ブロック(連続制御構造など)を持つことは良いことです。完全に関連付けられたキャッシュが望ましいです。