使用64位Visual C加速巨大C阵列的速度问题

Pae*_*ula 8 c performance 64-bit visual-studio-2010

我需要将大量数据读入缓冲区(大约20gig).我有192GB的非常快的DDram可用,所以没有内存大小的问题.但是,我发现以下代码进入缓冲区的速度越来越慢.Visual C分析器告诉我,12分钟执行时间的68%是在myFunc()循环内的2个语句中.我在一个非常快的dell上运行win7,64bit,每个有2个cpu,每个有6个物理内核(24个逻辑内核),所有24个内核在运行时都完全超出了.

#define TREAM_COUNT 9000
#define ARRAY_SIZE ONE_BILLION

#define offSet(a,b,c,d) ( ((size_t)  ARRAY_SIZE * (a)) + ((size_t) TREAM_COUNT * 800 * (b)) + ((size_t) 800 * (c)) + (d) )

void myFunc(int dogex, int ptxIndex, int xtreamIndex, int carIndex)
{
     short *ptx  =  (short *) calloc(ARRAY_SIZE * 20, sizeof(short));

    #pragma omp parallel for
    for (int bIndex = 0; bIndex < 800; ++bIndex)
          doWork(dogex, ptxIndex, carIndex);
}

 void doWork(int dogex, int ptxIndex, int carIndex)
{

    for (int treamIndex = 0; treamIndex < ONE_BILLION; ++treamIndex)
    {
         short ptxValue     =  ptx[ offSet(dogex, ptxIndex,   treamIndex, carIndex) ];
         short lastPtxValue =  ptx[ offSet(dogex, ptxIndex-1, treamIndex, carIndex) ];

         // ....
    }

}
Run Code Online (Sandbox Code Playgroud)

小智 6

该代码分配了20个10亿个短整数的块.在64位Windows框中,短整数是2个字节.所以分配大约是40千兆字节.

你说有24个核心,它们都被淘汰了.代码本身似乎没有显示任何并行性.代码并行化的方式可能会对性能产生深远的影响.您可能需要提供更多信息.

-

我怀疑,您的基本问题围绕缓存行为和内存访问限制.

首先,有两个物理CPU,每个六个核心,你将完全饱和你的内存总线.也许你有一个NUMA架构,但是代码中没有关于你的calloc()分配位置的控件(例如,你可能有很多代码存储在内存中,需要多跳才能到达).

超线程已打开.这有效地减少了高速缓存大小.鉴于代码是内存总线绑定,而不是计算绑定,超线程是有害的.(话虽如此,如果计算总是在缓存范围之外,那么这不会有太大变化).

目前尚不清楚(因为有些/多少?)代码被删除,如何访问数组以及访问模式和优化模式以实现缓存优化是性能的关键.

我在offset()的计算方法中看到的是,代码不断要求生成新的虚拟到物理地址查找 - 每个查询需要四次或五次内存访问.这本身就是表演.

我的基本建议是将阵列分解为2级缓存大小的块,为每个CPU提供一个块并让它处理该块.你可以并行完成.实际上,您可能可以使用超线程来预加载缓存,但这是一种更高级的技术.