【问题标题】:Is there a way to reuse pthreads?有没有办法重用pthreads?
【发布时间】:2012-08-29 09:50:29
【问题描述】:

我有一个被调用数百万次的函数,这个函数所做的工作是多线程的。这是函数:

void functionCalledSoManyTimes()
{
  for (int i = 0; i < NUM_OF_THREADS; i++)
  {
    pthread_create(&threads[i], &attr, thread_work_function, (void *)&thread_data[i]);
  }
  // wait
}

每次调用函数时我都会创建线程,并为每个线程提供其数据结构(在算法开始时设置一次)以在thread_work_function 中使用。 thread_work_functionsimply 处理一系列数组,thread_data 结构包含指向这些数组的指针和每个线程负责的索引。

尽管以这种方式对算法进行多线程处理确实将性能提高了 20% 以上,但我的分析表明对 pthread_create 的重复调用会导致显着的开销。

我的问题是:有没有办法在每次调用函数时不调用pthread_create 来实现我的目标?

问题已解决。

谢谢你们,非常感谢你们的帮助!我已经使用您的提示编写了解决方案here

【问题讨论】:

  • 你需要看一个线程池的概念。这里有一个线程池,等待工作。你安排这项工作,比如说在一个队列中 - 线程被阻塞,一个线程将拿起工作并执行它。这是一个相当普遍的概念,如果有可能,请从 APR(Apache Portable Runtime)之类的东西中提取此功能。

标签: c multithreading pthreads posix


【解决方案1】:

优雅地解决问题并不是那么容易。您可以将静态存储用于线程池,但是如果可以从多个线程调用 functionCalledSoManyTimes 本身会发生什么?这不是一个好的设计。

处理这种情况我会做的是在第一次调用时使用pthread_key_create 创建一个线程本地存储密钥(使用pthread_once),并在第一次使用pthread_setspecific 将你的线程池存储在那里functionCalledSoManyTimes 在给定线程中被调用。您可以向pthread_key_create 提供析构函数,当线程存在时将调用该函数,然后该函数可以负责向线程池中的工作线程发出信号以终止它们自己(通过pthread_cancel 或其他机制)。

【讨论】:

  • 有时您可以在楼上启动问题 - 要求 functionCalledSoManyTimes 的调用者传入由您为其提供的函数创建/销毁的线程池。如果调用者的代码看起来像 for (int i = 0; i &lt; SOMANY; ++i) functionCalledSoManyTimes();,这是一个简单的更改,如果从许多不相关的站点调用该函数则不容易,如果您想向调用者隐藏它是多线程的事实,那么简单但无用。
  • 这也是一个不错的解决方案,但我怀疑它通常不适用,特别是如果您想保留functionCalledSoManyTimes opaque/encapsulated 的实现。
  • 同意。我提到它是因为我想在引入隐藏共享状态之前排除它,无论是静态的还是线程本地的。如果我不能排除它,那是一个奖励。另一种可能性是告诉调用者他们正在创建和传递的是ManyTimesFunctionOptimizer。它秘密地包含一个线程池,并且您的函数实现被封装,除了它可以选择性地重用这个对象来获得速度提升。该对象是否包含线程池或记忆缓存(或两者)对于调用者是不透明的。
【解决方案2】:

只需启动一组固定的线程并使用线程间通信系统(例如环形缓冲区)将数据传递给处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-29
    • 2014-11-16
    • 2017-08-07
    • 2022-06-10
    • 2022-01-16
    • 2013-11-13
    • 2012-11-20
    • 1970-01-01
    相关资源
    最近更新 更多