如何在内存块(C )上进行位置

How to bitwise operate on memory block (C++)

本文关键字:位置 内存      更新时间:2023-10-16

是否有更好(更快/更有效的)在大型内存块上执行比特操作的方法?在寻找选项之后,我注意到STD具有成员std::bitset,并且还在想是否会更好(甚至可能)将大区域的存储器转换为bitset而不更改其值,然后执行操作,然后再执行将其类型切换回正常?

编辑/更新:我认为union可能在此处应用,以便将内存块分配为newint或其他东西,然后用作大型bitset。操作似乎可以根据这里所说的内容在整个集合中完成:http://www.cplusplus.com/reference/reference/bitset/bitset/bitset/operators/。

通常,没有比循环快的魔法方法。但是,您可以使编译器更容易通过牢记一些事情来优化循环:

  1. 一次将最大的可用整数类型加载到内存中。但是,如果缓冲区的长度不均匀地除以整数类型的大小,则需要小心。
  2. 如果可能的话,在一个循环迭代中在多个值上操作 - 这应该使编译器的矢量化变得更加简单。同样,您需要注意缓冲长度。
  3. 如果循环要多次在代码的简短部分上运行,请使用一个向下计数到零而不是向上的循环索引,并从数组长度中减去它 - 这使得CPU的分支预测变量变得更容易。出去发生了什么。
  4. 您可以使用编译器提供的显式向量扩展名,但这将使您的代码不那么便携。
  5. 最终,您可以在汇编中编写循环,并使用CPU提供的向量说明,但这是完全不可支配的。
  6. [编辑]此外,您可以使用OpenMP或类似的API将循环分配在多个线程之间,但这只有在您在大量内存上执行操作时才会改善。

c99具有常数字节的Xoring内存的示例,假设长为128位,则缓冲区的启动与16个字节对齐,而没有考虑点3。两个内存缓冲器上的钻头操作非常相似。

size_t len = ...;
char *buffer = ...;
size_t const loadd_per_i = 4
size_t iters = len / sizeof(long long) / loads_per_i;
long long *ptr = (long long *) buffer;
long long xorvalue = 0x5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5eLL;
// run in multiple threads if there are more than 4 MB to xor
#pragma omp parallel for if(iters > 65536)
for (size_t i = 0; i < iters; ++i) {
    size_t j = loads_per_i*i;
    ptr[j  ] ^= xorvalue;
    ptr[j+1] ^= xorvalue;
    ptr[j+2] ^= xorvalue;
    ptr[j+3] ^= xorvalue;
}
// finish long longs which don't align to 4
for (size_t i = iters * loads_per_i; i < len / sizeof(long long); ++i) {
    ptr[i] ^= xorvalue;
}
// finish bytes which don't align to long
for (size_t i = (len / sizeof(long long)) * sizeof(long long); i < len; ++i) {
    buffer[i] ^= xorvalue;
}