繁体   English   中英

在 C++ (VC++ 2010 Express) 上,双线程应用比单线程应用慢。 怎么解决?

[英]Two-threaded app is slower than single-threaded on C++ (VC++ 2010 Express). How to solve?

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

我做了这个最小的例子,除了它在不同线程中分配内存的事实之外,它与我的真实代码无关。

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);
}

它向我打印了这样的结果:

Task done in 16 seconds.
MT Task done in 19 seconds.

而且......我没想到会慢下来。 无论如何,是否可以在多个线程中更快地分配内存?

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

Visual C++ CRT 堆是单线程的1 ,因为malloc / free委托HeapAlloc / HeapFree在临界区执行(一次只有一个线程)。 一次从多个线程调用它们永远不会比单个线程快,而且由于锁争用开销,通常会更慢。

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


1有关HeapAlloc请参阅此说明:

当两个或多个线程尝试同时从同一堆分配或释放块时,序列化可确保互斥。 序列化的性能成本很小,但只要多个线程从同一堆分配和释放内存,就必须使用它。 设置HEAP_NO_SERIALIZE值可消除堆上的互斥。 如果没有序列化,使用相同堆句柄的两个或多个线程可能会尝试同时分配或释放内存,这可能会导致堆损坏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM