如何加快从内存到CPU的数据传输?

时间:2013-09-11 20:42:20

标签: c++ performance openmp bit-manipulation dma

我正在尝试加速一个popcount函数。这是代码:

extern ll LUT16[];
typedef long long ll;
typedef unsigned char* pUChar;
ll LUT16Word32Monobit(pUChar buf, int size) {
    assert(buf != NULL);
    assert(size > 0);
    assert(size % sizeof(unsigned) == 0);
    int n = size / sizeof(unsigned);
    unsigned* p = (unsigned*)buf;
    ll numberOfOneBits = 0;
    for(int i = 0; i < n; i++) {
        unsigned int val1 = p[i];
        numberOfOneBits += LUT16[val1 >> 16] + LUT16[val1 & 0xFFFF];
    }
    return numberOfOneBits;
}

以下是一些细节:

  • buf包含1 GB的数据
  • LUT16 [i]包含i的二进制表示中的一位的数量,对于所有0 <= i <1。 2 ^ 16

我尝试使用openMP来加快速度,但它不起作用。我必须补充说我正在使用MS Visual Studio 2010并且我已经启用了openMP指令。我相信openMP没有加速的原因之一是内存访问时间。有什么方法可以使用DMA(直接内存访问)吗?

另外,我应该警告你,我的openMP技能缺失了;这里所说的是openMP部分(与上面相同的代码):

#pragma omp for schedule(dynamic,CHUNKSIZE)
for(int i = 0; i < n; i++) {
    unsigned int val1 = p[i];
    numberOfOneBits += LUT16[val1 >> 16] + LUT16[val1 & 0xFFFF];
}

CHUNKSIZE设置为64.如果我将其设置得更低,结果会比串行版本更差,如果我将其设置得更高,则没有任何好处。

另外,我不想使用处理器提供的popcount指令,也不想使用SSE指令。

1 个答案:

答案 0 :(得分:3)

您的LUT16数组为512kB(假设long long为64位),这将完全破坏任意/随机数据的L1 / L2缓存性能(L1通常为32kB,L2通常为256KB)。

首先,您不需要long long。其次,请尝试LUT8。第三,只需使用内置的__popcnt内在函数。