为什么Windows有时使用临界区,有时使用原子列表进行堆锁?

时间:2016-11-15 17:56:06

标签: c++ windows multithreading

我遇到了一个问题,在并行操作期间,我在某些机器上遇到了严重的性能问题。例如,下面的代码在2芯片机器上可以很好地扩展,每个芯片有8个内核,但在2芯片机器上的扩展性很差,每个芯片有10个内核。

探查器指示具有2x10核心的计算机的缓存未命中,并指示对Windows RtlEnterCriticalSection的呼叫。这里的大部分时间花在malloc / free上。对于2x8核心机器,大部分时间花费在std::rand上(裸矩阵矩阵产品只是为了引入一些虚拟数字运算)。

对于2x8核心机器,我根本没有得到任何缓存未命中,而且我也没有'看到对RtlEnterCriticalSection的来电。相反,我看到调用RtlInterlockedPopSList看起来像Windows正在使用原子来管理堆锁。问题是为什么它会使用另一台机器上的关键部分,这对于多线程效率非常低?

     std::vector> futures;
     for (auto iii = 0; iii != 40; iii++) {
         futures.push_back(std::async([]() {
             for (auto i = 0; i != 100000 / 40; i++) {
                 const int size = 10;
                 for (auto k = 0; k != size * size; k++) {
                     double* matrix1 = (double*)malloc(100 * sizeof(double));
                     double* matrix2 = (double*)malloc(100 * sizeof(double));
                     double* matrix3 = (double*)malloc(100 * sizeof(double));

                     for (auto i = 0; i != size; i++) {
                         for (auto j = 0; j != size; j++) {
                             matrix1[i * size + j] = std::rand() / RAND_MAX;
                             matrix2[i * size + j] = std::rand() / RAND_MAX;
                         }
                     }

                     for (auto i = 0; i != size; i++) {
                         for (auto j = 0; j != size; j++) {
                             double sum = 0.0;
                             for (auto k = 0; k != size; k++) {
                                 sum += matrix1[i * size + k] * matrix2[k * size + j];
                             }
                             matrix3[i * size + j] = sum;
                         }
                     }
                     free(matrix1);
                     free(matrix2);
                     free(matrix3);
                 }
             }
         }));
     }
     for (auto& entry : futures)
       entry.wait();

0 个答案:

没有答案