約100万ポイントの大規模なデータセットで3つの整数(つまり[1 2 3])を検索したいと思います。
私は現在MATLABのマップ(ハッシュマップ)を使用しており、各ポイントに対して次のことを行っています。
key = sprintf('%d ', [1 2 3]); % 23 us
% key = '1 2 3 '
result = lookup_map( key ); % 32 us
ただし、これにはかなりの時間がかかります-100万ポイント* 55 us=55秒。
これをCUDAを使用してGPUに移動したいのですが、これにアプローチする最善の方法がわかりません。
4つの配列を転送key1, key2, key3, result
してからキーに対してバイナリ検索を実行することもできますが、これにはキーごとに20回の反復(2 ^ 20 = 1048576)が必要になります。次に、各スレッドからの同時メモリアクセスのために遅延も発生します。
CUDAでの並列(O(1)、理想的には)複数のキールックアップ用に最適化されたデータ構造はありますか?
Q:3つの整数の境界は何ですか?そして、どのようなデータが検索されますか?
整数キーは、現在0〜75,000の間である可能性がありますが、将来的にはさらに大きくなる可能性があります(200,000以上)。
この質問の目的のために、result
は0とデータセットのサイズの間の整数であると仮定することができます。
Q:3つの数値すべてを1つの64ビット数値にパックしませんか(数値あたり21ビットで0〜2,097,152の範囲になります)。そして、それを使用してスパース配列にインデックスを付けますか?
>> A = uint64(ones(10));
>> sparse_A = sparse(A)
??? Undefined function or method 'sparse' for input arguments of type 'uint64'.
>> A = int64(ones(10));
>> sparse_A = sparse(A)
??? Undefined function or method 'sparse' for input arguments of type 'int64'.
私のMATLABは64ビット数のスパース配列をサポートしていないようです。
これが他の誰かに役立つ場合に備えて、3つの<2^21符号なし整数から64ビットキーを作成する簡単な関数を作成しました。
function [key] = to_key(face)
key = uint64(bitsll(face(1), 42) + bitsll(face(2), 21) + rand(face(3),1));
end
Q:@Dennisから-論理インデックスを使用しないのはなぜですか?
テストしてみましょう!
% Generate a million random integers between 0 and 1000
>> M = int32(floor(rand(10000000,4)*1000));
% Find a point to look for
>> search = M(500000,1:3)
search =
850 910 581
>> tic; idx = M(:,1)==search(1) & M(:,2)==search(2)&M(:,3)==search(3); toc;
Elapsed time is 0.089801 seconds.
>> M(idx,:)
ans =
850 910 581 726
残念ながら、これには89801usが必要です。これは、既存のソリューション(55us)よりも1632倍遅くなります。これを100万回実行するには2.5時間かかります!
M
検索のたびにフィルタリングを試すことができます。
>> tic; idx1=M(:,1)==search(1); N=M(idx1,:); idx2=N(:,2)==search(2); N2=N(idx2,:); idx3 = N2(:,3)==search(3); toc;
Elapsed time is 0.038272 seconds.
これは少し高速ですが、それでもマップを使用するよりも696倍遅くなります。
私はこれについてもう少し考えていて、単一のキールックアップからその場でデータの一部を再生成する速度をプロファイリングすることにしました-潜在的な問題を考えると、3キールックアップよりも速いかもしれませんこのアプローチで。