【发布时间】:2019-09-11 13:52:59
【问题描述】:
我使用 OpenMP 来并行化调用,如下所示:
#pragma omp parallel for
for(std::size_t iter = 0; iter < visitors.size(); ++iter)
{
VisitorSPtr visitor_sp = visitors.at(iter);
dataSetPtr->accept(*(visitor_sp.get());
}
// End of
// #pragma omp parallel for
感谢#pragma omp parallel for 指令,每个访问者都在不同的线程中使用。美好的。
循环中调用的dataSetPtr->accept() 函数检查访问者是否已被用户取消,如下所示:
if(visitor.shouldStop())
break;
如果该调用返回 true,则不执行访问。当用户单击一个按钮并发出一个信号,该信号被传递给访问者,该访问者设置一个成员布尔变量以声明已请求取消时,该取消被捕获。但是信号没有到达访问者,if(visitor.shouldStop()) 没有用,也就是说,即使取消信号被正确发出,也永远不会评估为真。
连接是这样执行的(this 是建立连接的 MassDataIntegrator 对象实例,它接收取消信号并将其中继到访问者实例):
connect(this,
&MassDataIntegrator::cancelOperationSignal,
visitor_sp.get(),
&Visitor::cancelOperation,
Qt::QueuedConnection);
我的问题:如何从另一个线程中运行的代码修改 #pragma omp parallel for 循环中的对象?我认为通过使用指针这将是微不足道的。显然,我在这里遗漏了一些概念。有人可以帮我解决这个误解吗?感谢您的关注。
已解决
上面的连接调用由于某种原因不起作用(我将调查)。所以我尝试使用一个 lambda,从表面上看,它像这样直接访问 Visitor 实例(我注释掉了替换的代码以显示差异):
connect(this,
&MassDataIntegrator::cancelOperationSignal,
[visitor_sp](){visitor_sp->cancelOperation();});
//visitor_sp.get(),
//&TicChromTreeNodeCombinerVisitor::cancelOperation,
//Qt::QueuedConnection);
我们可以认为这个问题已经解决了。我该怎么做?
【问题讨论】:
-
请注意,在目前的表格中,我只能对您的问题给出一般性的回答。如果您的问题仍然存在并且您需要一个具体的答案,请创建一个minimal reproducible example - 最好不要 QT。
-
谢谢祖蓝的回答。我编辑了这个问题,因为经过一番挖掘后我发现其中存在编程错误。但是,我仍然不知道是否可以从该部分之外修改对象的状态(用于并行部分)。
-
好的,我现在已经解决了这个问题。我显然对作为对希望取消计算的用户的响应而发出的 Qt 信号存在问题:它没有到达 Visitor 实例。我已将解决方案添加到初始帖子中。
-
即使它看起来可以正常工作,如果您希望它正确且可移植,请记住我的回答。
-
是的,祖蓝,你是对的。我需要考虑这一点,尽管在当前的实现中,取消只能来自一个来源,并且会分别影响每个访问者。感谢您的帮助。