我想在大约一百万点的大型数据集中查找 3 个整数(即 [1 2 3])。
我目前正在使用 MATLAB 的 Map (hashmap),并且对于每一点我都在执行以下操作:
key = sprintf('%d ', [1 2 3]); % 23 us
% key = '1 2 3 '
result = lookup_map( key ); % 32 us
不过,这非常耗时 - 100 万点 * 55 我们 = 55 秒。
我想使用 CUDA 将其移至 GPU,但我不确定解决此问题的最佳方法。
我可以传输四个数组 - key1, key2, key3, result
,然后对键执行二进制搜索,但这需要每个键进行 20 次迭代 (2^20 = 1048576)。然后,由于每个线程的并发内存访问,我也会有延迟。
是否有针对 CUDA 中的并行(理想情况下为 O(1))多个键查找优化的数据结构?
问:三个整数的界限是多少?以及查找哪些数据?
整数键目前可以在 0 到 ~75,000 之间,但将来可能会更大(200,000+)。
出于这个问题的目的,我们可以假设result
是介于 0 和数据集大小之间的整数。
问:为什么不将所有三个数字打包成一个 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 位数字的稀疏数组。
如果这对其他人有帮助,我编写了一个快速函数来从三个 <2^21 无符号整数创建一个 64 位密钥:
function [key] = to_key(face)
key = uint64(bitsll(face(1), 42) + bitsll(face(2), 21) + rand(face(3),1));
end
问:来自@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 倍!运行一百万次需要 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.
这比使用 Map 快一点,但仍然慢 696 倍。
我一直在考虑这个问题,我决定分析从单个键查找动态重新生成一些数据的速度——考虑到潜在的问题,它可能比 3 键查找更快用这种方法。