【问题标题】:Why does my simple counting program take longer to run with multiple threads? (in C)为什么我的简单计数程序需要更长的时间才能运行多个线程? (在 C 中)
【发布时间】:2021-06-12 06:06:29
【问题描述】:

这是我的代码:

#define COUNT_TO 100000000
#define MAX_CORES 4

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
long long i = 0;

void* start_counting(void *arg){
    for(;;){

        pthread_mutex_lock(&mutex);

        if(i >= COUNT_TO){
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
        i++;
        pthread_mutex_unlock(&mutex);
        //printf("i = %lld\n", i);
    }
}

int main(int argc, char* argv[]){
    int i = 0;

    pthread_t * thread_group = malloc(sizeof(pthread_t) * MAX_CORES);

    for(i = 0; i < MAX_CORES; i++){
        pthread_create(&thread_group[i], NULL, start_counting, NULL);
    }

    for(i = 0; i < MAX_CORES; i++){
        pthread_join(thread_group[i], NULL);
    }

    return 0;
}

【问题讨论】:

  • 因为互斥锁管理不是免费的,而且它的非线程单循环版本可能会优化到几乎没有。
  • 所有线程都由锁/解锁序列化。也就是说,没有有效的并行化,但存在运行同步和线程交换的成本。仅仅在问题上抛出线程是不够的。您实际上需要分解工作,以便它可以并行运行而没有主要的互锁,并且工作需要足够重要以使其值得线程切换的开销。
  • 我在测试中删除了互斥锁,它改善了多线程的运行时间,但它仍然比单线程慢得多。我是多线程的新手,但我觉得这不应该发生?
  • 简短的回答是,正在解决的问题不值得并行化,与正在完成的工作相比,线程开销的成本太高了。在任何情况下,移除锁都不是正确的答案,因为这意味着代码不是线程安全的——它们都试图在竞争条件下读取和递增相同的变量,这意味着代码在功能上变得不正确。
  • 不知道 C 是否允许这样做,但在其他语言中,使用智能编译器,您的程序会被编译为一个程序,该程序只需在第一个线程中将 COUNT_TO 分配给 i其他线程几乎什么都不做。然后,您创建的线程越多,您的开销就越大,而根本不会改变结果。

标签: c multithreading concurrency runtime


【解决方案1】:

这是你的线程所做的:

  1. 读取i的值。
  2. 增加我们读取的值。
  3. 写回i的增量值。
  4. 转到步骤 1。

很清楚,在另一个线程完成步骤 1 之后但在完成步骤 3 之前,另一个线程无法读取 i 的值。因此执行步骤 1、2 或 3 的两个线程之间不能有重叠。

因此,您所有的线程都在争夺对同一资源的访问权——i(或保护它的互斥锁)。如果没有对其中一个或两者的独占访问权,任何线程都无法取得有用的前进进展。鉴于此,使用多个线程没有任何好处,因为一次只有一个线程可以完成有用的工作。

【讨论】:

    猜你喜欢
    • 2012-09-08
    • 2015-03-12
    • 2019-07-02
    • 2020-08-28
    • 2015-09-05
    • 2011-11-07
    • 2015-09-17
    • 2020-11-08
    • 1970-01-01
    相关资源
    最近更新 更多