【发布时间】:2022-06-29 16:48:09
【问题描述】:
世界,
我尝试使用多线程运行 C++ 应用程序(在 VS 中编译为 .exe),并为此使用 QThread 或 omp-parallelization。在使用 umfpack 求解从这些矩阵构建的方程系统之前,每个线程都会执行多次内存分配/解除分配以执行大型矩阵计算。现在,当我使用太多线程时,我会降低性能,因为线程在执行此操作时会相互阻塞。我已经读过内存(取消)分配一次只能用于一个线程(如互斥条件)。
我已经尝试过的:
- 尽我所能减少大量重新分配
- 使用不同的并行化方法(Qt 与 omp)
- 随机更改保留和提交的堆栈/堆大小
- 将 umfpack 数组设为线程私有
在我的设置中,在性能下降之前,我可以使用 ~4 个线程(每个线程使用 ~1.5 GB RAM)。有趣的是——但我还无法理解——只有在几个线程完成并且新线程接管之后,性能才会降低。另请注意,线程之间不相互依赖,没有其他阻塞条件,每个线程运行的时间大致相同(约 2 分钟)。
有没有“简单的方法” - 例如以某种方式设置堆/堆栈 - 来解决这个问题?
这里有一些代码sn-ps:
// Loop to start threads
forever
{
if (sem.tryAcquire(1)) {
QThread *t = new QThread();
connect(t, SIGNAL(started()), aktBer, SLOT(doWork()));
connect(aktBer, SIGNAL(workFinished()), t, SLOT(quit()));
connect(t, SIGNAL(finished()), t, SLOT(deleteLater()));
aktBer->moveToThread(t);
t->start();
sleep(1);
}
else {
//... wait for threads to end before starting new ones
//... eventually break
}
qApp->processEvents();
}
void doWork() {
// Do initial matrix stuff...
// Initializing array pointers for umfpack-lib
static int *Ap=0;
static int *Ai=0;
static int *Ax=0;
static int *x=0;
static int *b=0;
// Private static Variablen per thread
#pragma omp threadprivate(Ap, Ai, Acol, Arow)
// Solving -> this is the part where the threads block each other, note, that
there are other functions with matrix operations, which also (de-)/allocate a
lot
status = umfpack_di_solve (UMFPACK_A, Ap,Ai,Ax,x,b, /*...*/);
emit(workFinished());
}
【问题讨论】:
-
您可以尝试预分配到池中,或者切换到不序列化所有分配和释放的不同分配器。见stackoverflow.com/q/147298/103167
-
谢谢。使用新的分配器来实例化线程对象是否就足够了,还是我必须在我的代码中交换所有“新”语句?
-
一个好的分配器可以选择替换系统分配器(在 C++ 中它被命名为
::operator new()),所以你不必重写代码。根据您在矩阵运算中发生争用的说法,仅更改 Thread 对象的分配是不够的。 -
提醒——还有第三种选择——静态。您可以在静态数据中保留一个喇叭大数组
标签: c++ multithreading memory-management