C - 交换两个相同大小的内存块的最快方法? (解决方案可行性)

标签 c memory swap avx2

这个问题是 this one 的延伸。在这里我提出两种可能的解决方案,我想知道它们的可行性。我正在使用带有 GCC/ICC 编译器的 Haswell 微架构。我还假设内存是对齐的。

选项 1 - 我已经分配了一个内存位置并执行 3 次内存移动。 (我使用 memmove 而不是 memcpy 来避免复制构造函数)

void swap_memory(void *A, void* B, size_t TO_MOVE){

    memmove(aux, B, TO_MOVE);
    memmove(B, A, TO_MOVE);
    memmove(A, aux, TO_MOVE);
}

选项 2 - 使用 AVX 或 AVX2 加载和存储,利用对齐的内存。对于这个解决方案,我认为我交换了 int 数据类型。

void swap_memory(int *A, int* B, int NUM_ELEMS){

    int i, STOP_VEC = NUM_ELEMS - NUM_ELEMS%8;
    __m256i data_A, data_B;

    for (i=0; i<STOP_VEC; i+=8) {
        data_A = _mm256_load_si256((__m256i*)&A[i]);
        data_B = _mm256_load_si256((__m256i*)&B[i]);

        _mm256_store_si256((__m256i*)&A[i], data_B);
        _mm256_store_si256((__m256i*)&B[i], data_A);
    }

    for (; i<NUM_ELEMS; i++) {
        std::swap(A[i], B[i]);
    }
}

选项 2 是最快的吗?还有我没有提到的另一种更快的实现吗?

最佳答案

如果您确定内存已对齐,那么使用 AVX 可能是最好的选择。请注意,显式执行此操作可能不可移植 - 最好对指针进行修饰,以便知道它们是对齐的(例如使用 aligned 属性或类似属性。)

最有可能的选项 2(或语义上执行此操作的选项)可能会更快,因为指针不受限制或任何其他东西。编译器可能不知道重新排序内存或保持“aux”不变是安全的。

此外,选项 2 可能更加线程安全,具体取决于 aux 的设置方式。

使用本地临时文件和 memcpy 来 block 或什至一次性使用该临时文件可能会很好,因为 gcc 可能能够对其进行矢量化。避免使用外部临时对象,并确保所有结构都装饰对齐。

关于C - 交换两个相同大小的内存块的最快方法? (解决方案可行性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37329329/

相关文章:

c++ - 编译器控件如何帮助在 C++ 中分配和释放内存?

c++ - 使用管理器和 vector 时出现内存错误

string - 寻找将一个字符串转换为另一字符串的最小交换次数,其中字符串可能包含重复的字符

c++ - for std::queue remove all of element swap 和 pop 的时间差

c - C中的动态列表头疼,反向打印列表?为什么?

c - getchar 的意外行为

c - 静态变量未初始化为零

arrays - 如何快速交换两个日期

c - 带有大小写开关和枚举的工作日

c - 运行时检查失败 #2 - 变量 'd' 周围的堆栈已损坏。 (Visual Studio下的C编程)