0

我是并发编程的新手。我实施了一项 CPU 密集型工作,并测量了我可以获得多少加速。但是,当我增加#threads 时,我无法获得任何加速。

该程序执行以下任务:

  • 有一个共享计数器可以从 1 计数到 1000001。
  • 每个线程执行以下操作,直到计数器达到 1000001:
    • 以原子方式递增计数器,然后
    • 循环运行 10000 次。

总共要执行 1000001*10000 = 10^10 次操作,所以我应该能够在增加#threads 时获得良好的加速。

这是我实现它的方式:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdatomic.h>

pthread_t workers[8];
atomic_int counter; // a shared counter

void *runner(void *param);

int main(int argc, char *argv[]) {
  if(argc != 2) {
    printf("Usage: ./thread thread_num\n");
    return 1;
  }

  int NUM_THREADS = atoi(argv[1]);
  pthread_attr_t attr;

  counter = 1; // initialize shared counter
  pthread_attr_init(&attr);

  const clock_t begin_time = clock(); // begin timer
  for(int i=0;i<NUM_THREADS;i++)
    pthread_create(&workers[i], &attr, runner, NULL);

  for(int i=0;i<NUM_THREADS;i++)
    pthread_join(workers[i], NULL);

  const clock_t end_time = clock(); // end timer

  printf("Thread number = %d, execution time = %lf s\n", NUM_THREADS, (double)(end_time - begin_time)/CLOCKS_PER_SEC);

  return 0;
}

void *runner(void *param) {
  int temp = 0;

  while(temp < 1000001) {
    temp = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
    for(int i=1;i<10000;i++)
      temp%i; // do some CPU intensive work
  }

  pthread_exit(0);
}

但是,当我运行我的程序时,我无法获得比顺序执行更好的性能!!

gcc-4.9 -std=c11 -pthread -o my_program my_program.c
for i in 1 2 3 4 5 6 7 8; do \
        ./my_program $i; \
    done
Thread number = 1, execution time = 19.235998 s
Thread number = 2, execution time = 20.575237 s
Thread number = 3, execution time = 25.161116 s
Thread number = 4, execution time = 28.278671 s
Thread number = 5, execution time = 28.185605 s
Thread number = 6, execution time = 28.050380 s
Thread number = 7, execution time = 28.286925 s
Thread number = 8, execution time = 28.227132 s

我在 4 核机器上运行程序。

有没有人有改进程序的建议?或者任何线索为什么我不能得到加速?

4

1 回答 1

0

这里唯一可以并行完成的工作是循环:

for(int i=0;i<10000;i++)
      temp%i; // do some CPU intensive work

gcc,即使是最低优化级别,也不会为temp%i;void 表达式发出任何代码(反汇编并查看),因此这实质上变成了一个空循环,它将执行得非常快 - 在多个线程运行的情况下的执行时间不同的核心将由包含不同核心之间的原子变量乒乓的缓存线控制。

在看到加速之前,您需要让这个循环实际完成大量工作。

于 2015-04-29T02:01:10.063 回答