私はこれを読んでいました 質問 、私は彼が示したコードについてもっと質問したかった、すなわち
for(i = 0; i < 20; i++)
for(j = 0; j < 10; j++)
a[i] = a[i]*j;
質問は、
その人は言った、
「a [i]に10回アクセスすると、内側のループが同じメモリアドレスを呼び出すので、これは時間的局所性の例だと思います。しかし、上記のループにも空間的局所性はありますか?」
私は彼の推測に同意しません。 a [i]によって生成される参照は空間的な局所性である必要があるため(ブロック内の次の要素を参照します)。私は正しいですか?
まず、var
への参照は、一時的にローカルまたは空間的にローカルではなく時間的局所性、これは不適切な文法です。マイナーポイント。
さて、あなたの質問に移りましょう。
時間的局所性の原則は、2つの命令が比較的短い時間枠内で同じ場所を参照することを示しています。たとえば、指定されたコードでは、a[i]
が頻繁に参照され、a[i] = a[i] * 2
やa[i] = a[i] * 3
などの命令が非常に接近して実行されます。このスコープを見ると、j
とa[i]
への参照は一時的にローカルであると言えます。 a[i]
が参照されるたびにi
が参照されるため、i
への参照も一時的にローカルです。ただし、指定されたコードの最後の行がa[j] = a[j] * j
のようなものである場合、i
への参照は、少なくとも内部ループの範囲内では、一時的にローカルではありません。[1]。
空間的局所性の原則は、2つの命令が連続したメモリ位置を参照することを示しています。 a[i]
への参照は、これの良い例です。これは、(ほとんどの場合)a[0]
とa[1]
がメモリ内で互いに隣接していると想定できるためです。
最初の2つは基本的にこれをカバーしていますが、引用されたテキストは正しく、コードは空間的な局所性も示しています。
[1]-一般に、ローカリティについて話しているときは、それがRAMか、L1キャッシュか、それとも何を持っているかに関わらず、メモリ階層の特定のレベルのコンテキストになります。最も限定された意味を除いて、i
とj
の両方への参照は一時的にローカルです。
この質問の他の回答、他のいくつかの質問、ウィキペディアを読んだ後でも得られなかったので、この回答を書きます(それはもっと混乱しています)。
この場合、少し紛らわしい/複雑な用語を理解するために多くの時間とエネルギーを費やしていると思います。 「空間的」と「時間的」という用語に注意を払わなかったとき、私は理解しやすくなりました。
基本から始めましょう。
キャッシュとは何か、つまりメインメモリよりもアクセスが速い場所を理解してみましょう。カッコいい。しかし、この場所は限られていて高価なので、賢く使うべきです。しかし、あなた(またはOS)は、何をキャッシュに入れ、何を入れないかをどのように決定しますか?将来何が必要になるかを知る方法があるはずです。ああ、将来の予測! (マイノリティリポート!ベルを鳴らしますか?).
プログラムが将来何を必要とするかを決定する何らかの方法があるはずです。常識とコードを使用すると、コードの一部は本質的に反復的であると言えます-例-ループ!ループ内に変数iがある場合、近い将来何度も何度もアクセスされることがわかります。これが時間的局所性の背後にある原則です。一時的にローカルであるため、キャッシュに入れることができます。
別の領域では、コードが線形データ構造(例:配列)を使用していて、それもインデックスの増分を伴うループ内にある場合、現在必要なのは(たとえば)の3番目の場所だけですが、簡単にわかります。このデータ構造では、その線形データ構造のインデックスが1増えるため、すぐに次の場所も必要になります。したがって、次のいくつかの場所にもデータを取り込むことができれば素晴らしいと思います。これが空間的局所性の背後にある原則です。次のいくつかの場所は空間的にローカルであるため、キャッシュに入れることができます。
ローカリティの概念は、基本的に、キャッシュを取り込むためのデータと命令を識別して、キャッシュミスを減らし、この特別な場所を効果的に利用できるようにすることです。
時間的局所性と空間的局所性の両方を定義することから始めましょう。
Temporal Locality --Temporal Localityは、フェッチされている現在のデータまたは命令がすぐに必要になる可能性があることを意味します。したがって、そのデータまたは命令をキャッシュメモリに保存して、メインメモリで同じデータを再度検索することを回避し、時間を節約する必要があります。
空間的局所性-空間的局所性とは、フェッチされている現在のメモリ位置に近い命令またはデータを意味し、近い将来必要になる可能性があります。
sum = 0;
for (i = 0; i < arr.length; i++)
sum += arr[i];
return sum;
この例を見ると、ここでは変数sumが何度も使用されており、Temporal Localityを示しています。次に、配列arrの値に順番にアクセスしています(つまり、arr [0]、arr [1]、arr)。 [2]、...など、配列が連続(隣接)メモリブロックであるため、空間局所性を示しているため、現在のメモリ位置に近いデータがフェッチされています。
今この例を見てください
for(i = 0; i < 20; i++)
for(j = 0; j < 10; j++)
a[i] = a[i]*j;
ここでは、2番目のループのa [i]が何度も使用され、次に変数jが空間的局所性を示す順序でアクセスされているため、時間的局所性がわかります。
外側のループは、空間的な局所性の例です。内部のforループ呼び出しのアドレスを順次インクリメントします。
内側のループは、時間的な局所性を示しています。まったく同じメモリアドレスが連続して10回アクセスされ、そのたびにjが乗算されます。
最初の2つの質問については、iとj(ループカウンター)の両方が時間的局所性の非常に良い例です。
局所性は、メモリへの呼び出しを最小限に抑えるためにキャッシュによって適用される尺度です。命令がまだキャッシュにないメモリアドレスの値を知る必要がある場合、命令はメモリにアクセスし、周囲のすべてのメモリ位置もキャッシュに格納します。