![](/img/trans.png)
[英]C++ multithreaded version of creating vector of random numbers slower than single-threaded version
[英]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.