我有一个具有以下结构的循环:
我的循环被多次调用(这是我程序的主循环),我希望第二步尽可能快。
第二步的简单实现是使用memcmp
:
char* calc;
char** list;
int k, n, i;
for(i = 0; i < n; i++) {
if (!memcmp(calc, list[i], k)) {
printf("Matches array %d", i);
}
}
你能想到更快的方法吗?一些事情:
以下是我的一些想法:
memcmp
进行二进制搜索。xor
将我的数组折叠到自己的所有查找数组上)并使用内置{ {1}}与How to compare more than two numbers in parallel?一样。我知道这里有SSE4.2。你认为去矢量化/ sse是一个好主意吗?如果是,您认为最好的方法是什么? 我想说这不是早期优化,但性能在这里至关重要,我需要外循环尽可能快。 感谢
EDIT1:看起来http://schani.wordpress.com/tag/c-optimization-linear-binary-search-sse2-simd/提供了一些有趣的想法。在PCMPGT
列表上进行二进制搜索似乎是要走的路..
答案 0 :(得分:7)
最佳解决方案将取决于要匹配的阵列数量,阵列的大小以及它们更改的频率。我会考虑避免进行比较。
假设要比较它的数组列表不会经常更改并且你有很多这样的数组,我会创建每个数组的哈希值,然后当你进行比较时,哈希你正在测试的东西。然后,您只需要比较哈希值。使用像SHA256这样的散列,你可以依赖它作为正指针和负指示符(即散列匹配足以说明数组匹配以及不匹配的散列足以说明数组不同)。如果您有(比方说)1,000,000个阵列进行比较而几乎没有变化,这将非常有效,因为计算哈希值将比1,000,000个阵列比较更快。
如果您的阵列数量稍微小一点,您可能会考虑使用更快的非加密哈希值。例如,简单地将数组模块256中的字节相加的“散列”(这是一个可怕的散列并且你可以做得更好)将消除比较(例如)目标数组空间的255/256的需要。然后,您可以只比较那些所谓的'哈希'匹配的那些。有很多类似哈希的东西,比如CRC-32,可以快速计算。
在任何一种情况下,您都可以通过哈希(模数X)查找以确定实际比较哪些数组。
你建议k很小,N是中等的(即大约1000)。我猜速度将围绕内存缓存。不在这里访问1,000个小阵列将非常有帮助。
如果阵列的变化频率与比较相似,那么以上所有内容都将毫无用处。
添加(假设您正在查看64字节或类似字节)。我会研究一个非常快速的非加密哈希函数。例如,请查看:https://code.google.com/p/smhasher/wiki/MurmurHash3
每32位字看起来像3-4个指令来生成哈希。然后,您可以将结果截断为(例如)12位,用于4096条目哈希表,冲突很少(每个桶都链接到目标数组)。这意味着您将查看大约30条指令来计算哈希值,然后查看每个桶条目的一条指令(期望值1)以查找列表项,然后按预期命中(即介于0和1之间)进行一次手动比较。因此,不是比较1000个数组,而是比较0和1个数组,并生成一个哈希。如果你不能比较30个指令中的999个阵列(我猜不是!),这显然是一个胜利。
答案 1 :(得分:2)
我们可以假设我的东西适合64位,甚至32位。如果它 不是,我可以哈希它,所以它可以。但现在,最快的方法是什么 查找我的哈希是否存在于预先计算的哈希值列表中?
这是一种元回答,但是......如果你的问题归结为:如何有效地找出某个32位数字是否存在于其他32位数字的列表中,这是一个问题IP路由器一直处理,因此可能值得研究网络文献,看看是否有一些东西可以从他们的算法中适应。例如见http://cit.mak.ac.ug/iccir/downloads/SREC_07/K.J.Poornaselvan1,S.Suresh,%20C.Divya%20Preya%20and%20C.G.Gayathri_07.pdf
(虽然,我怀疑它们已针对搜索大量项目进行了优化,而不是用例...)
答案 2 :(得分:0)
你可以做一个XOR而不是memcmp吗?
或对数组中每个元素进行caclulate哈希并对其进行排序以搜索哈希
但哈希会花费更多时间。除非你能提出更快的哈希
答案 3 :(得分:0)
另一种方法是从列表中预构建树并使用树搜索 例如,列表:
aaaa
aaca
acbc
acca
bcaa
bcca
caca
我们可以得到这样的树
root
-a
--a
---a
----a
---c
----a
--c
---b
----c
---c
----a
-b
--c
---a
----a
---c
----a
-c
--a
---c
----a
然后在树的每个级别进行二元搜索