Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 双CPU内存分配性能_C++_Multithreading_Performance_Memory Management_Cpu - Fatal编程技术网

C++ 双CPU内存分配性能

C++ 双CPU内存分配性能,c++,multithreading,performance,memory-management,cpu,C++,Multithreading,Performance,Memory Management,Cpu,当我在具有2个CPU的特定服务器上使用多线程代码时,我遇到了一个问题。服务器运行在Windows 7 x64上,具有Bi Xeon E5-2697Wv2 12核2,7 GHz;64 Gb RAM(8X8 Gb 1866 MHz);主板超级微型X9DAI。我的可执行文件是使用Visual Studio MSVC 2013生成的,并使用OpenMP进行多线程处理 现在的问题是,我使用1个线程比24个线程有更好的性能。。。此问题仅在此计算机上可见,当我连接探查器(CodeXL)时,我得到以下结果:

当我在具有2个CPU的特定服务器上使用多线程代码时,我遇到了一个问题。服务器运行在Windows 7 x64上,具有Bi Xeon E5-2697Wv2 12核2,7 GHz;64 Gb RAM(8X8 Gb 1866 MHz);主板超级微型X9DAI。我的可执行文件是使用Visual Studio MSVC 2013生成的,并使用OpenMP进行多线程处理

现在的问题是,我使用1个线程比24个线程有更好的性能。。。此问题仅在此计算机上可见,当我连接探查器(CodeXL)时,我得到以下结果:

  • 1个线程:~3%的执行时间在malloc/free(~3/~2)内
  • 24个线程:~64%的执行时间在malloc/free内(~33%/~31%)
代码很复杂,我无法给出一个示例,但基本上它是一个蒙特卡罗代码,有少量的动态分配(初始化阶段创建所有需要的数据),在一个事件开始时只保留一个动态分配来存储事件数据。代码不包含任何互斥体,每个线程在计算开始和结束时都不进行任何通信

我在服务器和双CPU架构方面的知识非常有限,我想知道我是否可以做些什么来避免这个问题(BIOS选项?),我猜是有一个控制器可以选择使用哪个CPU RAM,如果这个操作会使速度变慢

谢谢你的阅读

编辑: 我编写了一个小基准测试来评估malloc/free的性能下降,下面是代码:

#include <omp.h>
#include <afx.h>
#include <vector>
#include <fstream>
#include <iostream>
#include <chrono>

// malloc allocation size tab
int allocSize[] =
{
    4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072
};

int main()
{
    // number max of thread
    int nbThreadMax = omp_get_max_threads();
    // malloc/free iteration per bench
    unsigned int nbIteration = 1000000;

    // Empty res tab
    std::vector<double> emptyRes(16, 0.);
    // Duration per thread
    std::vector<std::vector<double>> avgDuration(nbThreadMax, emptyRes);

    int nbThread = 1;
    unsigned int idxt = 0;
    while (nbThread <= nbThreadMax)
    {
        // Current bench result
        std::vector<std::vector<double>> threadResult(nbThread, emptyRes);

        std::cout << "Thread : " << nbThread << std::endl;

        // Create parrallel region
        #pragma omp parallel num_threads(nbThread)
        {
            int nt = omp_get_thread_num();

            for (unsigned int i = 0; i < 16; ++i)
            {
                int allocationSize = allocSize[i];

                std::chrono::time_point<std::chrono::system_clock> start, end;
                start = std::chrono::system_clock::now();
                for (unsigned int j = 0; j < nbIteration; ++j)
                {
                    void* pData = malloc(allocationSize);
                    free(pData);
                }
                end = std::chrono::system_clock::now();

                threadResult[nt][i] += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / 1000.;
            }
        }

        // Sum
        for (unsigned int i = 0; i < 16; ++i)
        {
            for (unsigned int j = 0; j <= idxt; ++j)
            {
                avgDuration[idxt][i] += threadResult[j][i];
            }
            // /!\  Normalize for one thread /!\
            avgDuration[idxt][i] /= nbThread;
        }

        ++idxt;
        // Increase thread number (X2)
        if (nbThread >= nbThreadMax)
            break;
        if (nbThread * 2 > nbThreadMax)
            nbThread = nbThreadMax;
        else
            nbThread = nbThread * 2;
    }

    // Write results
    {
        std::ofstream ofs("resultats.csv");
        ofs << "NbThread;";
        for (unsigned int i = 0; i < 16; ++i)
        {
            ofs << allocSize[i] << ";";
        }
        ofs << std::endl;

        int nbThread = 1;
        for (unsigned int n = 0; n < idxt; ++n)
        {
            ofs << nbThread << ";";
            for (unsigned int i = 0; i < 16; ++i)
            {
                ofs << avgDuration[n][i] << ";";
            }
            ofs << std::endl;
            nbThread = nbThread * 2;
        }

        ofs.close();
    }
}
#包括
#包括


这种结果是问题还是正常性能下降?

BIOS选项太离奇了。最简单的解决方案是稍微偏离标准C方法,使用本机Windows方法

第一个测试是将
malloc/free
替换为
HeapAlloc
。这里的好处是
HeapAlloc
可以支持多个堆,并且使用
HEAP\u NO\u SERIALIZE
这些堆中的每一个都可以是单线程的。这并不意味着您必须在同一线程上调用
HeapFree
。您可以在工作线程上调用
HeapAlloc
,将结果存储在分配的内存块中,加入主线程(此处为内存屏障),然后在主线程上从工作线程收集所有数据,并从主线程调用
HeapFree
。由于工作线程不再存在,因此不存在序列化风险


第二个改进(如有必要)是检查NUMA支持。最好将线程固定到CPU,并从连接到该特定CPU的4xGB内存中分配内存。但这要复杂得多。

BIOS选项太奇特了。最简单的解决方案是稍微偏离标准C方法,使用本机Windows方法

第一个测试是将
malloc/free
替换为
HeapAlloc
。这里的好处是
HeapAlloc
可以支持多个堆,并且使用
HEAP\u NO\u SERIALIZE
这些堆中的每一个都可以是单线程的。这并不意味着您必须在同一线程上调用
HeapFree
。您可以在工作线程上调用
HeapAlloc
,将结果存储在分配的内存块中,加入主线程(此处为内存屏障),然后在主线程上从工作线程收集所有数据,并从主线程调用
HeapFree
。由于工作线程不再存在,因此不存在序列化风险


第二个改进(如有必要)是检查NUMA支持。最好将线程固定到CPU,并从连接到该特定CPU的4xGB内存中分配内存。但这要复杂得多。

标准C11/C++11中的一种方法是为每个线程创建一个条目缓存。在
mymalloc
中,检查单个缓存项是否可以满足请求(无需锁定)。如果没有,请按照常规的
malloc


大部分智能都在
myfree
中。如果已经有一个缓存项,那么您需要决定要做什么:保留最旧的、保留最新的、保留最小的、保留最大的,或者可能是其他一些策略。(如果您需要此处的大小,
mymalloc
必须通过
sizeof(size\u t)
进行过度分配,并在请求的大小前加前缀)。

标准C11/C++11中的一种方法是为每个线程创建一个条目缓存。在
mymalloc
中,检查单个缓存项是否可以满足请求(无需锁定)。如果没有,请按照常规的
malloc


大部分智能都在
myfree
中。如果已经有一个缓存项,那么您需要决定要做什么:保留最旧的、保留最新的、保留最小的、保留最大的,或者可能是其他一些策略。(如果您需要此处的大小,
mymalloc
必须通过
sizeof(size\u t)
进行过度分配,并在请求的大小前加前缀)。

2个CPU上的24个线程?线程不是性能的圣杯。特别是在NUMA机器上是的,2个CPU上有24个线程,我没有精确地确定RAM有8X8Gb。你是说我什么都做不了?@πάνταῥεῖ 由于每个CPU都有12个核心,因此非常简单reasonable@user3513887我忽略了每个处理器都有12个内核。2个CPU上有24个线程?线程不是性能的圣杯。特别是在NUMA机器上是的,2个CPU上有24个线程,我没有精确地确定RAM有8X8Gb。你是说我什么都做不了?@πάνταῥεῖ 由于每个CPU都有12个核心,因此非常简单reasonable@user3513887我忽略了每个都有12个核心。