2

当在 Linux shell 中使用线程在 C 中编程时,我试图减少线程开销,基本上是降低 CPU 时间(并提高效率)。

现在在程序中创建了许多线程,并且需要在它终止之前完成一项工作。由于互斥,只有一个线程可以同时完成工作。

我知道一个线程在开始之前完成一项工作需要多长时间

当有一个线程在做这项工作时,其他线程必须等待。他们检查是否可以完成工作的方式是是否满足条件变量。

对于等待线程,如果他们使用该条件变量等待,则使用此特定代码等待(a、b、c 和 d 只是任意的东西,这只是一个示例):

while (a == b || c != d){
    pthread_cond_wait(&open, &mylock);
}

这效率如何?代码中发生了什么pthread_cond_wait?是一个不断检查条件变量的while循环(在幕后)吗?

另外,由于我知道一个线程将花费多长时间,所以我首先执行关于最短作业的调度策略是否更有效?或者这无关紧要,因为在执行这项工作的任何线程组合中,程序将花费相同的时间来完成。换句话说,是否首先使用最短作业会降低其他线程等待的 CPU 开销?由于最短的工作首先似乎减少了等待时间。

4

2 回答 2

4

用一个线程解决您的问题,然后如果您还看不到需要最少锁定的途径,请向我们寻求帮助,以确定公开并行化的最佳位置。要使用的最佳线程数取决于您使用的计算机。使用超过 n+1 个线程没有多大意义,其中 n 是程序可用的处理器/内核数。为了减少线程创建开销,给每个线程多个作业是个好主意。

以下是对您的澄清编辑的回应:

现在在程序中创建了许多线程,并且需要在它终止之前完成一项工作。由于互斥,只有一个线程可以同时完成工作。

不可以。如上所述,最多应创建 n+1 个线程。你说的互斥是什么意思?我认为互斥是“只有一个线程在其工作队列中包含任务 x”。这意味着没有其他线程需要锁定任务 x。

当有一个线程在做这项工作时,其他线程必须等待。他们检查是否可以完成工作的方式是是否满足条件变量。

给每个线程一个独立的任务列表来完成。如果作业 x 是作业 y 的先决条件,那么作业 x 和作业 y 理想情况下应该在同一个列表中,这样线程就不必处理任一作业上的线程互斥对象。你探索过这条路吗?

而 (a == b || c != d){ pthread_cond_wait(&open, &mylock); 这效率如何?pthread_cond_wait 代码中发生了什么?是一个不断检查条件变量的while循环(在幕后)吗?

为了避免未定义的行为,mylock 必须在调用 pthread_cond_wait 之前被当前线程锁定,所以我假设您的代码调用 pthread_mutex_lock 在进入此循环之前获取 mylock 锁。

  1. pthread_mutex_lock 阻塞线程直到它获得锁,这意味着一次一个线程可以执行 pthread_mutex_lock 和 pthread_cond_wait 之间的代码(pre-pthread_cond_wait 代码)。
  2. pthread_cond_wait 释放锁,允许其他线程运行 pthread_mutex_lock 和 pthread_cond_wait 之间的代码。在 pthread_cond_wait 返回之前,它会一直等待,直到它可以再次获取锁。此步骤重复 adhoc while (a == b || c != d)
  3. 稍后在任务完成时调用 pthread_mutex_unlock。在此之前,一次只有一个线程可以执行 pthread_cond_wait 和 pthread_mutex_unlock 之间的代码(pthread_cond_wait 后代码)。此外,如果一个线程正在运行 pre-pthread_cond_wait 代码,则没有其他线程可以运行 post-pthread_cond_wait 代码,反之亦然。

因此,您不妨运行将作业存储在优先级队列中的单线程代码。至少你不会有不必要的和过多的上下文切换。正如我之前所说,“用一个线程解决你的问题”。在您有衡量标准之前,您无法就优化节省了多少时间做出有意义的陈述。

另外,由于我知道一个线程将花费多长时间,所以我首先执行关于最短作业的调度策略是否更有效?或者这无关紧要,因为在执行这项工作的任何线程组合中,程序将花费相同的时间来完成。换句话说,是否首先使用最短作业会降低其他线程等待的 CPU 开销?由于最短的工作首先似乎减少了等待时间。

如果您要执行调度策略,请在单线程项目中执行。如果您相信并发会帮助您快速解决问题,那么将您完成的单线程项目暴露给并发并派生测试来验证您的信念。我建议以线程不必共享工作的方式公开并发性。

于 2013-02-24T02:06:48.687 回答
2

Pthread 原语通常相当有效。阻塞的东西在阻塞时通常不消耗或可以忽略不计的 CPU 时间。如果您遇到性能问题,请先查看其他地方。

不用担心调度策略。如果您的应用程序设计为一次只能运行一个线程,那么您将失去最初线程化的大部分好处,同时增加所有成本。(如果你没有强加所有的成本,比如锁定共享变量,因为一次只运行一个线程,你就是在自找麻烦。)

于 2013-02-24T06:31:52.917 回答