我想要对大型的位移数组进行异或操作,以下是便于解释的可移植版本的函数。我该如何改进这个计算过程?我尝试过使用AVX2,但没有看到太多改进。目前对于下面示例中显示的DB,处理所有内容需要50毫秒,即12 GB/s。我将非常感谢任何改进计算过程的建议。
更新: 这是godbolt链接:https://godbolt.org/z/j14av3fGq 我还在两个实例上运行了这段代码。
Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz 运行在 MacOS 13.6 上,16 GB DDR4 RAM,编译器为 Apple clang version 15.0.0 (clang-1500.0.40.1)
AWS r7i.2xlarge Intel(R) Xeon(R) Platinum 8488C 运行在 Ubuntu 上,64 GB DDR5 RAM,编译器为 g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
令人惊讶的是,Xeon 上的速度是其两倍慢!!
我正在使用编译器标志 O3
更新2:我觉得这可能会有用,上述代码是从外部函数中调用的,类似于以下示例(非运行代码)
#include <iostream>
uint64_t partition_size = 4096;
uint64_t entry_size = 32; // bytes
uint64_t DB_size = 16777216;
uint64_t *DB = new uint64_t[DB_size * entry_size/64];
//partition_index will be a random multiple of partition_size, e.g. 0, 8192, 4096 etc
//random_offset will be a random number in [0, partition_size]
void xor_shifted_arrays(uint32_t partition_index, uint32_t random_offset, uint64_t *result)
{
auto uint64_per_entry = entry_size / sizeof(uint64_t);
int shift_offset;
uint32_t shift;
for (int i = 0; i < partition_size ; i = i + 1)
{
shift = (i + random_offset) & (partition_size - 1);
shift_offset = shift * uint64_per_entry;
for (int j = 0; j < uint64_per_entry; j=j+1){
result[shift_offset + j] = result[shift_offset + j] ^ DB[partition_index + j];
}
partition_index = partition_index + uint64_per_entry;
}
}
更新: 这是godbolt链接:https://godbolt.org/z/j14av3fGq 我还在两个实例上运行了这段代码。
Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz 运行在 MacOS 13.6 上,16 GB DDR4 RAM,编译器为 Apple clang version 15.0.0 (clang-1500.0.40.1)
AWS r7i.2xlarge Intel(R) Xeon(R) Platinum 8488C 运行在 Ubuntu 上,64 GB DDR5 RAM,编译器为 g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
令人惊讶的是,Xeon 上的速度是其两倍慢!!
我正在使用编译器标志 O3
更新2:我觉得这可能会有用,上述代码是从外部函数中调用的,类似于以下示例(非运行代码)
void outer_function(){
uint64_t *result1 = new uint64_t[partition_size];
uint64_t *result2 = new uint64_t[partition_size];
uint64_t number_partitions = 4096;
for (int i=0; i< number_partitions; i++){
xor_shifted_arrays(i*partition_size, some_rnd_gen(), result1)
}
for (int i=0; i< number_partitions; i++){
xor_shifted_arrays(i*partition_size, some_rnd_gen(), result2)
}
}
-O3
级别)。如今,我们不再受限于2013年的SSE2问题,内存对齐对于良好的SIMD性能通常不再那么重要(或者如果内存对齐,向编译器保证对其对于AVX来说有时是完全无关紧要的)。但是,重要的是编译器已经做得很好,您不需要使用内嵌函数来实现这一点。 - undefinedDB
仍然可以是一个连续的数组,你只需要在结果/DB的每个块的前0.5 MiB上进行循环,然后是第二个,第三个,以此类推,并在你当前代码的外部循环中执行。在大型Xeon处理器上,每个核心私有的L2缓存比L3缓存要快得多,每个核心都有1到2 MiB的L2缓存。(SPR上是2 MiB。) - undefined