次の blog には、リンクリストに対する配列の利点に関する記述があります。
配列のキャッシュの局所性が向上しているため、パフォーマンスが大幅に向上します。
どういう意味ですか?キャッシュの局所性がパフォーマンスの大きなメリットをどのように提供できるのか理解できません。
私の答えを参照してください 空間的および時間的局所性について 。
特に、配列は連続したメモリブロックであるため、配列の大部分は最初のアクセス時にキャッシュにロードされます。これにより、配列の将来の要素に比較的すばやくアクセスできます。一方、リンクリストは必ずしも連続したメモリブロックにあるとは限らず、キャッシュミスが多くなる可能性があり、アクセスに時間がかかります。
大きな構造体の配列data
およびリンクリストl_data
の次のメモリレイアウトを検討してください。
Address Contents | Address Contents
ffff 0000 data[0] | ffff 1000 l_data
ffff 0040 data[1] | ....
ffff 0080 data[2] | ffff 3460 l_data->next
ffff 00c0 data[3] | ....
ffff 0100 data[4] | ffff 8dc0 l_data->next->next
| ffff 8e00 l_data->next->next->next
| ....
| ffff 8f00 l_data->next->next->next->next
この配列をループする場合、ffff 0000
への最初のアクセスでは、メモリにアクセスして取得する必要があります(CPUサイクルでの非常に遅い操作)。ただし、最初のアクセス後、アレイの残りの部分はキャッシュ内にあり、後続のアクセスははるかに高速になります。リンクリストを使用すると、ffff 1000
への最初のアクセスでもメモリにアクセスする必要があります。残念ながら、プロセッサはこの場所を直接囲むメモリをキャッシュします。つまり、ffff 2000
まで続きます。ご覧のとおり、これはリストの他の要素を実際にはキャプチャしません。つまり、l_data->next
にアクセスするときは、再びメモリに移動する必要があります。
通常、配列を使用する場合、互いに近いアイテムにアクセスします。これは、配列に順番にアクセスする場合に特に当てはまります。
メモリにアクセスすると、そのチャンクがさまざまなレベルでキャッシュされます。 キャッシュの局所性は、連続した操作がキャッシュ内に存在する可能性が高いため、高速になることを意味します。配列では、キャッシュ内にシーケンシャル要素アクセスの可能性を最大化します。
リストでは、反例として、リストに順番に表示されるアイテムがメモリ内で互いに近くに実際に配置されるという保証はありません。これは、キャッシュヒットが少なくなり、パフォーマンスが低下することを意味します。