nブロックのデータを持つアルゴリズムがあり、Nブロックのすべての可能なペアリングを実行するには、常に2つのブロックがメモリに存在する必要があるような、すべてのブロックに対して操作を実行する必要があるとします。
すべてのデータがNを実行しているマシンのメモリに収まらないようにNが大きい場合:
これらの操作を順序付けして、操作を完了するためにディスクからデータをフェッチする必要がある回数を最小限に抑えるための最適な方法は何ですか。他のすべてと比較ブロック1の単純なアプローチは明らかに非常に最適ではありません
メモリはランダムアクセスで高速です。永続的なストレージはそうではありません。永続ストレージはストリームとして高速です。これらの仮定があなたの状況に当てはまる場合は、それらに対応するソリューションを設計します。
私がこのような組み合わせの問題に対処するときはいつでも、目の前に九九の表があると役に立ちます。
乗算に2つの数値が必要であるのと同じように、演算には2つのブロックが必要です。この表を斜めに折りたたむと、反対側にも同じ数字が表示されることに注意してください。乗算と同様に、演算が commutative であると仮定すると、1つの三角形で作業を複製しないことで、作業の半分以上の複製を節約できます。
私がここで単純化されたアプローチに向かっていると思うなら、あなたは正しいですが、私と一緒にいると、きちんとした何かが表示されます。
これが いくつかのループ であり、メモリ内の配列でこれを行うと正常に機能します。
int[] arr={1,2,3,4};
for (int i=0; i<arr.length; i++)
for (int j=i+1; j<arr.length; j++)
System.out.println("{"+arr[i]+","+arr[j]+"}");
出力:
{1,2}
{1,3}
{1,4}
{2,3}
{2,4}
{3,4}
ここに私があなたに気づかせたいきちんとしたものがあります:彼らができる限り、ここの数は増え続けます。彼らがそうしない唯一の時は、私たちがすでに行われた仕事をスキップしているときです。これを書き直して、これらをストリームで取り込み、不要な部分をスキップすることができます。必要な限り、左の値をメモリに保持できます。
可能な改善点は、一度に1つの値のみを変更することです。これは、作業を次の順序で整理することを意味します。
{1,2}
{1,3}
{1,4}
{3,4}
{2,4}
{2,3}
ただし、これには、永続ストレージへのアクセスが順次よりランダムであることが必要です。大丈夫かもしれないあなたのブロックのサイズに応じて。 I/Oには、512バイトから64キロバイトまでの独自のブロックサイズがあります。あなたのフォーマットに依存します。
ブロックサイズがI/Oブロックサイズよりも小さい場合、I/Oブロックサイズの範囲内でランダムアクセスを行うことができます。それ以外の場合は、可能な限り順次実行するのがよいでしょう。