我有一个单线程Linux应用程序,我想并行。它读取数据文件,创建对象并将其放置在向量中。然后,它调用每个对象上的计算密集型方法(.5秒+)。我想与对象创建并行调用该方法。当我查看QT和TBB时,我对其他选择开放。

我计划在矢量为空时启动线程。每个人都会打电话 makeSolids (下图),它具有一个ther循环,该循环可以运行,直到interpdone == true,并且已经处理了向量中的所有对象。但是,在线程方面,我是N00B,并且一直在寻找现成的解决方案。

QtConcurrent::map(Iter begin,Iter end,function()) 看起来很简单,但是我不能在变化的矢量上使用它,可以吗?我该如何告诉它等待更多数据?

我还看着英特尔的TBB,但是如果我使用的话,我的主线程看起来会停下来 parallel_for 或者 parallel_while. 。由于推荐他们的内存管理器(开放的Cascade的MMGT在多线程时的性能较差),因此这很臭。

/**intended to be called by a thread
\param start the first item to get from the vector
\param skip how many to skip over (4 for 4 threads)
*/
void g2m::makeSolids(uint start, uint incr) {
  uint curr = start;
  while ((!interpDone) || (lineVector.size() > curr)) {
    if (lineVector.size() > curr) {
      if (lineVector[curr]->isMotion()) {
        ((canonMotion*)lineVector[curr])->setSolidMode(SWEPT);
        ((canonMotion*)lineVector[curr])->computeSolid();
      }
      lineVector[curr]->setDispMode(BEST);
      lineVector[curr]->display();

      curr += incr;
    } else {
      uio::sleep(); //wait a little bit for interp
    }
  }
}

编辑:总而言之,在主线程填充向量的同时处理向量的最简单方法是什么?

有帮助吗?

解决方案

很难判断您是否一直在深入思考这个问题,而且还有比您允许的更多,或者您是否只是过度思考,或者您只是对螺纹的警惕。

读取文件并创建对象很快;一种方法很慢。依赖性是每个连续的CTOR取决于上一个CTOR的结果 - 有点奇怪 - 但否则没有数据完整性问题,因此似乎没有任何东西可以受到静音等的保护。

为什么这比这样的东西更复杂(在粗略的伪代码中):

while (! eof)
{
    readfile;
    object O(data);
    push_back(O);
    pthread_create(...., O, makeSolid);
}


while(x < vector.size())
{
    pthread_join();
    x++;
}

如果您不想在主体中的连接上循环循环,那么通过传递TID的矢量来等待线程等待它们。

如果创建的对象/线程的数量是疯狂的,请使用线程池。或放置计数器是创建循环,以限制在连接运行之前可以创建的线程数的数量。

其他提示

首先,要从线程中受益,您需要找到类似的慢速任务让每个线程要做。您说您的每个对象处理需要.5S+,您的文件读取 /对象创建需要多长时间?这很容易成为十分之一或千分之一的时间,在这种情况下,您的多线程方法将产生可忽视的好处。如果是这样,(是的,我会尽快回答您的原始问题,而不是),然后考虑同时处理多个对象。鉴于您的处理需要一段时间,线程创建开销并不重要,因此您可以简单地将主文件读取/对象创建线程产生一个新线程,然后将其引导到新创建的对象。然后,主线程继续读取/创建后续对象。读取/创建所有对象并启动了所有处理线程后,主线程“加入”(等待)工作线程。如果这会创建太多线程(数千),则限制允许主线程获得多远:它可能会读取/创建10个对象,然后加入5,然后读取/创建10,加入10,读取/创建/创建/创建10,加入10等。直到完成。

现在,如果您真的希望读取/创建与处理并行,但是要序列化的处理,那么您仍然可以使用上述方法,但在每个对象之后加入。如果您只用这种方法来设计此操作,那就很奇怪,但是很好,因为您可以轻松地尝试上面的对象处理并行性。

另外,您可以使用仅涉及主线程的更复杂的方法(OS在程序启动时创建的)以及主线程必须启动的单个工作线程。它们应使用MUTEX进行协调(一个变量确保相互排他性,这意味着不连续,访问数据)和条件变量,该变量允许工作人员线程有效阻止,直到主线程提供了更多的工作。术语 - 静音和条件变量 - 是Linux使用的POSIX线程中的标准术语,因此应在您感兴趣的特定库的说明中使用。简单地,工作线程等待直到主读/创建线程广播它是一个唤醒信号,表明另一个对象已准备好处理。您可能需要有一个带有最后一个完全创建的,即准备好处的对象的索引的计数器,以便工作线程可以维护其处理的对象的计数并沿就绪的对象进行移动,然后再一次检查条件变量。

@Caleb:很 - 也许我应该强调 积极的 线程。 GUI线程应始终被视为一个。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top