C++ C/C+中最快的u_int64_t[8]数组比较+;

C++ C/C+中最快的u_int64_t[8]数组比较+;,c++,c,arrays,stdvector,memcmp,C++,C,Arrays,Stdvector,Memcmp,比较C/C++中两个u_int64[8]数组的最快方法是什么 数组1位于std::vector(~10k个元素)内数组2位于动态分配结构内。(这里是不是没有假阳性?) 我的(伪C)实现: typedef struct { u_int64_t array[8]; }work_t; /* alloc and fill array work_t* work = new (std::nothrow) work_t etc... */ for(u_int32_t i=0

比较C/C++中两个
u_int64[8]
数组的最快方法是什么

数组1位于
std::vector
(~10k个元素)内数组2位于动态分配结构内。(这里是不是没有假阳性?)

我的(伪C)实现:

typedef struct {            
    u_int64_t array[8];
}work_t;

/* alloc and fill array work_t* work = new (std::nothrow) work_t etc... */

for(u_int32_t i=0; i < some_std_vector.size(); i++) {       

                if((some_std_vector[i]->array[0] == work->array[0]) &&
                   (some_std_vector[i]->array[1] == work->array[1]) &&
                   (some_std_vector[i]->array[2] == work->array[2]) &&
                   (some_std_vector[i]->array[3] == work->array[3]) &&
                   (some_std_vector[i]->array[4] == work->array[4]) &&
                   (some_std_vector[i]->array[5] == work->array[5]) &&
                   (some_std_vector[i]->array[6] == work->array[6]) &&
                   (some_std_vector[i]->array[7] == work->array[7])) {
                    //...do some stuff...
                }
}
typedef结构{
u_int64_t数组[8];
}工作;;
/*alloc和fill数组工作\u t*工作=新的(std::nothrow)工作\u t等*/
对于(u_int32_t i=0;i数组[0]==功->数组[0])&&
(一些标准向量[i]->数组[1]==功->数组[1])&&
(一些标准向量[i]->数组[2]==功->数组[2])&&
(一些标准向量[i]->数组[3]==功->数组[3])&&
(一些标准向量[i]->数组[4]==功->数组[4])&&
(一些标准向量[i]->数组[5]==功->数组[5])&&
(一些标准向量[i]->数组[6]==功->数组[6])&&
(一些标准向量[i]->数组[7]==功->数组[7])){
//…做些事情。。。
}
}

目标平台是Linux x86_64 gcc 4.9.2,循环在
pthread
中,使用
tcmalloc
,代码使用-O2编译,根据您使用的设备和编译器,您可以尝试一些“特定”问题。例如,在某些编译器中,有一些技术允许从内存执行大范围加载,并因此实现最快的多重比较。还有一些方法可以手动展开循环,因此执行速度更快。但这取决于编译器。
您可以尝试一些方法,检查汇编代码,看看哪种方法最快。

我想真正回答这个问题的唯一方法是编写两个例程,一个使用您提供的循环,另一个使用memcmp。然后,分析并查看散件,看看哪一个看起来最有效。(你也可能会痴迷于使用剖析器。)

您还可以在汇编中编写一个自定义例程来直接比较它们(即,专门用于比较您正在查看的内容的自定义版本的memcmp),并将其与其他两个进行比较


不管怎样,我同意其他人的观点,一切都可能非常接近(使用现代编译器);但是,如果您真的想保持对它的记忆,您必须使用探查器对其进行测试,并且/或者具备查看创建的程序集的技能,并知道哪一个程序集的视觉速度更快。

以下是一些提高速度的建议

如果可能,使用局部变量 使用局部变量或将变量作为引用传递,而不是使用指针,例如->运算符。编译器可能会生成额外的代码,用于将指针加载到寄存器中,然后取消对寄存器的引用以获取值

使用处理器的数据缓存 大多数现代处理器都有数据缓存。如果可以用数据加载多个变量,然后进行比较,则可以调用处理器的数据缓存

此外,还要设计数据,使其有效地适合数据缓存线。这意味着数据成员(包括数组)应该彼此相邻或非常接近

块比较 在最低级别,您将比较多个连续字节。正如其他人提到的,通过使用内存比较函数,您可能会获得更好的性能

另一个建议是通过将值加载到单独的变量中来帮助编译器,比较值:

for (/*...*/)
{
//...
    uint64_t a1 = some_std_vector[i]->array[0];
    uint64_t a2 = some_std_vector[i]->array[1];
    uint64_t a3 = some_std_vector[i]->array[2];
    uint64_t a4 = some_std_vector[i]->array[3];

    uint64_t b1 = work->array[0];
    uint64_t b2 = work->array[1];
    uint64_t b3 = work->array[2];
    uint64_t b4 = work->array[3];

    if ((a1 == b1) && (a2 == b2) && (a3 == b3) && (a4 == b4))
    {
       //...
    }
}
这里的概念是首先将变量加载到多个寄存器中,然后比较寄存器

查看汇编语言和概要文件 对于答案中介绍的所有技术,最好的方法是编写一个,检查汇编语言和概要文件。记住将优化级别设置为高速


如果您的进程有一些特殊指令可以加快速度,那么您需要验证编译器是否正在使用它们,或者是否有理由不使用它们

我做了一些测试,查看了gcc memcmp、glibc memcmp和上面的代码。glibc-2.20 memcmp是fastes方式,因为它使用特定于平台的优化(在我的例子中)


gcc memcmp要慢得多。(,使用-fno内置memcmp编译)

上述操作可能与使用memcmp一样快或更快,尽管这在很大程度上取决于特定的编译器和CPU设计。
memcmp()==0
始终是可以的,因为这是一个原始内存比较。这不仅是一个很好的提示,还可以让编译器进行优化(SSE,管道)。但真正优秀的编译器会将代码解释为
memcmp()