2011-12-21 10 views
10

これはGoogleのインタビューの質問です。 64GBのRAMを搭載し、すべての整数(8バイト)を含む2台のマシンで128GBのデータ全体をソートします。少量のRAMを追加することもできます。これを拡張して、1000台のマシンに格納されたデータをソートします。RAMサイズより大きなデータをソートする

私は外部の並べ替えを考え出しました。そこで、データ全体をチャンクに分割し、マージソートを使用します。それは最初にチャンクをソートして戻し、もう一度それらを賢明にしてマージします。より良い方法がありますか?複雑さは何でしょうか?

+0

分割して再作成します。最終的なマージのために単一のマシンを避けることは可能ですか? Yes:基数ソート。 – wildplasser

+0

@wildplasser - それは問題ではありません。マージは外部I/Oより高速です。したがって、マージ処理は、128GBのデータを宛先ドライブに書き込む時間に制限されます。 n + 1デバイスの場合、残りのドライブに書き込むためにnウェイマージを使用できます。これにより、n個のマシンがn個の作業ドライブ上にn個のデータチャンクを並列に作成することができますが、最終的なマージはデスティネーションドライブのI/O速度によって制限されます。 – rcgldr

+0

共有ファイルシステムを(単一の)マシンとみなすことができます。それはまだファンネルロックです。 – wildplasser

答えて

0

クイックソートを個別に使用して64GBのソートを行い、64GBアレイの両方の外部メモリ保持ポインタを使用すると、RAM1とRAM2の順番でデータ全体を保持し、ポインタがRAM1のポインタより小さければ、ポインタの値がRAM2にある場合は、ポインタがRAM1の終わりに達するまで、値をRAM2にスワップします。

は、すべてのN RAMをソートするのと同じコンセプトを採用しています。それらのペアをとり、上記の方法でソートしてください。 N/2ソートRAMが残っています。上記の再帰的に同じ概念を使用してください。

+1

各再帰でマシンペアをとるアルゴリズムはどのようになりますか? – Dialecticus

4

ChingPingは、サブセットごとにO(n log n)ソートを行い、その後に線形マージ(要素の入れ替え)を行います。クイックソートの問題(とn log nの大半は、n個のメモリを必要とするという問題です。代わりに定数メモリを使用するSmoothSortを使用し、O(n log n)で実行することをお勧めします。

最悪あなたが何か持っている場合のシナリオは次のとおりです。

両方のセットを逆に並べられ
setA = [maxInt .. 1] 
setB = [0..minInt] 

を、その後合併は逆の順序である

- ChingPingのソリューションの(IMOより明確に)説明がされています。 :

Have a pointers 'pointerA', 'pointerB' initialized at the beginning of each array 
While setA's pointer is not at the end 
    if (setA[pointerA] < setB[pointerB]) 
    then { pointerA++; } 
    else { swap(setA[pointerA], setB[pointerB]); pointerB++; } 

セットは現在両方ともソートされるべきです。

+1

'クイックソートの問題はn個のメモリを必要とする ' - ([Sedgewickの変形]を参照)([Sedgewickの変形]を参照)(https://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms)最初)。 – greybeard

+0

要素を交換することによる線形マージは機能していません。 setA = {0,1,6,7}、setB = {2,3,4,5}の場合を考えてみよう。線形マージの後、結果はsetA = {0,1,2,3}、setB = {6,7,4,5}となります。問題は、setAの要素がsetBの要素より大きい場合、setBの挿入ソートに似た何らかのO(n^2)が必要であるということです。 – rcgldr

0

すでに2台のマシンのケースに対する回答があります。

ソートされる128GBのデータが1台のハードドライブ(または任意の外部デバイス)に1つのファイルとして保存されているとします。何台のマシンやハードドライブを使用しても、オリジナルの128GBファイルを読み込み、ソートされた128GBファイルを書き込む時間は同じです。唯一の節約は、ソートされたデータのチャンクを作成する内部RAMベースのソートの間に発生します。残りのハードドライブに1つのソートされた128GBファイルにnウェイ・マージを行うためにn + 1個のハード・ドライブとマージするのにかかる時間は同じであり、残りの128GBソート・ファイルを書き込む時間ハードドライブ。

n台のマシンの場合、データは128GB/nチャンクに分割されます。マシンのそれぞれは、ランダムアクセスオーバヘッドを減らすために、一度に64MBの読み込みサブチャンクを交互に読み出すことができるため、 "最後の"マシンは、それまでのすべてのマシンがすべてのチャンクを読み込むのを待っていません。

n個のマシン(それぞれ64GBラム)とn> = 4のn + 1ハードドライブの場合、O(n)時間の複雑さを持つ基数ソートを各マシンで使用して、n個の作業で32GB以下のチャンクを作成できますハードドライブを同時に起動し、宛先ハードドライブにnウェイをマージします。

大きなnの利益を制限するリターンが小さくなる点があります。 n> 16を越えるところでは、内部のマージスループットがディスクのI/O帯域幅より大きくなる可能性があります。マージプロセスがI/OバウンドではなくCPUバウンドの場合、I/O時間よりも大きなマージオーバーヘッドと並行してチャンクを作成する時間は、CPUオーバーヘッドのトレードオフになります。

+0

私はこの問題を理解しているので、ハードドライブは使用しないでください。ソートするデータの総量は* n * \ * 64 GBです。* n *はマシンの台数です。 – ruakh

+0

@ruakh - 各マシンに64GBがある場合、ソートの前後に128GBのデータが保存されますか? – rcgldr

+0

ソートの前:ホスト間で任意に配布されます。ソート後:ホスト間でソートされて分散されます。 – ruakh

関連する問題