C++ 在C+上,双线程应用程序比单线程应用程序慢+;(VC&x2B;&x2B;2010年快车)。如何解决?

C++ 在C+上,双线程应用程序比单线程应用程序慢+;(VC&x2B;&x2B;2010年快车)。如何解决?,c++,windows,multithreading,performance,winapi,C++,Windows,Multithreading,Performance,Winapi,我有一些分配大量内存的程序,我希望通过在线程上拆分任务来提高它的速度,但这只会使我的程序变慢 我做了一个简单的例子,除了在不同的线程中分配内存之外,它与我的实际代码无关 class ThreadStartInfo { public: unsigned char *arr_of_5m_elems; bool TaskDoneFlag; ThreadStartInfo() { this->TaskDoneFlag = false;

我有一些分配大量内存的程序,我希望通过在线程上拆分任务来提高它的速度,但这只会使我的程序变慢

我做了一个简单的例子,除了在不同的线程中分配内存之外,它与我的实际代码无关

class ThreadStartInfo
{
public:
    unsigned char *arr_of_5m_elems;
    bool TaskDoneFlag;

    ThreadStartInfo()
    {
        this->TaskDoneFlag = false;
        this->arr_of_5m_elems = NULL;
    }

    ~ThreadStartInfo()
    {
        if (this->arr_of_5m_elems)
            free(this->arr_of_5m_elems);
    }
};

unsigned long __stdcall CalcSomething(void *tsi_ptr)
{
    ThreadStartInfo *tsi = (ThreadStartInfo*)tsi_ptr;

    for (int i = 0; i < 5000000; i++)
    {
        double *test_ptr = (double*)malloc(tsi->arr_of_5m_elems[i] * sizeof(double));
        memset(test_ptr, 0, tsi->arr_of_5m_elems[i] * sizeof(double));
        free(test_ptr);
    }

    tsi->TaskDoneFlag = true;
    return 0;
}

void main()
{
    ThreadStartInfo *tsi1 = new ThreadStartInfo();
    tsi1->arr_of_5m_elems = (unsigned char*)malloc(5000000 * sizeof(unsigned char));
    ThreadStartInfo *tsi2 = new ThreadStartInfo();
    tsi2->arr_of_5m_elems = (unsigned char*)malloc(5000000 * sizeof(unsigned char));
    ThreadStartInfo **tsi_arr = (ThreadStartInfo**)malloc(2 * sizeof(ThreadStartInfo*));
    tsi_arr[0] = tsi1;
    tsi_arr[1] = tsi2;

    time_t start_dt = time(NULL);
    CalcSomething(tsi1);
    CalcSomething(tsi2);
    printf("Task done in %i seconds.\n", time(NULL) - start_dt);
    //--

    tsi1->TaskDoneFlag = false;
    tsi2->TaskDoneFlag = false;
    //--

    start_dt = time(NULL);
    unsigned long th1_id = 0;
    void *th1h = CreateThread(NULL, 0, CalcSomething, tsi1, 0, &th1_id);
    unsigned long th2_id = 0;
    void *th2h = CreateThread(NULL, 0, CalcSomething, tsi2, 0, &th2_id);

    retry:
    for (int i = 0; i < 2; i++)
        if (!tsi_arr[i]->TaskDoneFlag)
        {
            Sleep(100);
            goto retry;
        }

    CloseHandle(th1h);
    CloseHandle(th2h);

    printf("MT Task done in %i seconds.\n", time(NULL) - start_dt);
}

而且。。。我没想到会慢下来。在多个线程中是否有加快内存分配的方法?

除了由于在
TaskDoneFlag
上缺少同步而导致一些未定义的行为外,所有线程都在重复调用
malloc
/
free

VisualC++ CRT堆是<>强>单线程 Malc /<代码>免费委托//<代码> HeAPFLeFE/<代码>,它在关键部分(一次只一个线程)执行。一次从多个线程调用它们的速度永远不会比单个线程快,而且通常由于锁争用开销而较慢

减少线程中的分配或切换到另一个内存分配器,如jemalloc或tcmalloc


1见本说明:

当两个或多个线程试图同时从同一堆分配或释放块时,序列化可确保互斥。序列化的性能代价很小,但每当多个线程从同一堆分配和释放内存时,都必须使用它。设置
HEAP\u NO\u SERIALIZE
值可以消除堆上的互斥。如果没有序列化,使用相同堆句柄的两个或多个线程可能会同时尝试分配或释放内存,这可能会导致堆损坏


由于TaskDoneFlag上缺少同步而导致行为未定义-我不这么认为。使用
TaskDoneFlag
,例如在示例中使用非常不好的方法(好的方法是在任务计数中使用联锁递减线程,当它达到零设置事件时,主线程等待该事件,而不是在循环中休眠)。但我认为不需要在
TaskDoneFlag
上进行任何同步。编译器无法删除
tsi->TaskDoneFlag=true行(或更早执行)。喜欢并且不能通过自身的true或false对
tsi_arr[i]->TaskDoneFlag
(对他来说是未知的
Sleep
)和
TaskDoneFlag
原子的读取进行重新排序或丢弃。bool不是原子的(否则就不需要锁指令前缀)。不同步地访问同一变量是错误的。然而,考虑到强大的x86内存模型和VC++10编译器,最终结果可能会如预期的那样。这并不意味着代码可以移植到其他平台(但是的,这在本例中可能并不重要)。bool是原子的,因为这里只能有2个值-0(false)或不是0(true),因为这是it和原子的-我们只能查看false(0)或true(任何不是0)我们不能查看某些“部分”链接上的修改和答案不正确。即使从正式的C++视图-布尔只有2个阶段,我们不能读取一些不是真的,也不是假的。只有在执行RMW操作时才需要锁定。但如果我们只从bool-lock中写入或读取,则不需要。这里的内存模型根本不相关(在具体的代码示例中),平台(bool如何实现,它包含多少字节)这里不相关-bool-type,能够包含两个值中的一个:true或false。-这是主要的。所以无论有没有任何“同步”,我们都会读到布尔真或假。内存模型-是关于访问不同内存位置的顺序,它是可视和修改顺序。但这里只有一个内存位置。代码不是最优的。但它不是UB,也不是依赖于平台的建议不可扩展讨论;这段对话已经结束。
Task done in 16 seconds.
MT Task done in 19 seconds.