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 は、最小の最適化レベルであっても、void 式のコードを発行しないtemp%i;(逆アセンブルして確認する) ため、これは本質的に空のループになり、非常に高速に実行されます。異なるコアは、異なるコア間でピンポンするアトミック変数を含むキャッシュラインによって支配されます。

スピードアップが見られる前に、このループが実際にかなりの量の作業を行うようにする必要があります。

于 2015-04-29T02:01:10.063 に答える