並列バージョンでは、10000000 (1000 万) x 1000 回の反復と、スレッドごとに 5000000 (500 万) x 1000 回の反復を実行しています。私の経験では、起動時のオーバーヘッドを無視できるものにするのに十分な作業です。結果は私には正しいようです。
2 つのコアと 2 つのスレッドの場合、(少なくとも 2 つのワーカー スレッド間で) タイムスライスは関係ありません。スケジューラは、スレッドを別々のコアに配置してそこに保持するのに十分なほどスマートだからです。
いくらかの劣化を確認するには、キャッシュを介してメモリを移動する必要があります。これにより、各コンテキスト スイッチがキャッシュから一部のデータを削除することで実際にパフォーマンスが低下するようになります。これが私が得ている実行時間です:
./a.out 2 500000000
スレッド数 = 2
各スレッドの反復回数 = 250000000
合計所要時間 = 5.931148
./a.out 1000 500000000
スレッド数 = 1000
各スレッドの反復回数 = 500000
合計所要時間 = 6.563666
./a.out 2000 500000000
スレッド数 = 2000
各スレッドの反復回数 = 250000
総所要時間 = 7.087449
そして、これがコードです。私は基本的に、指定されたスレッド間で大きな配列を分割し、配列内のすべての項目を二乗しています:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
long* array;
int length;
int threads;
void *tfunc(void *arg) {
int n = (int)arg;
int i;
int j;
int x;
long sum = 0;
//printf("%d\n",*n);
int start = n * (length / threads);
int end = (n + 1) * (length / threads);
for (i=start; i<end; i++) {
array[i] = array[i] * array[i];
//printf("%d\n",i);
}
return(0);
}
double timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return (double)tp.tv_sec + tp.tv_usec / 1000000.;
}
int main(int argc, char *argv[]) {
int numberOfIterations = atoi(argv[2]);
int numberOfThreads = atoi(argv[1]);
int i;
printf("Number of threads = %d\n",numberOfThreads);
printf("Number of iterations in each thread = %d \n", numberOfIterations / numberOfThreads);
pthread_t workerThreads[numberOfThreads];
int *arg = &numberOfIterations;
array = (long*)malloc(numberOfIterations * sizeof(long));
length = numberOfIterations;
threads = numberOfThreads;
int result[numberOfThreads];
double timeTaken;
timeTaken = timestamp();
for(i=0; i<numberOfThreads; i++) {
result[i] = pthread_create(workerThreads+i, NULL, tfunc, (void*)i);
}
for(i=0; i<numberOfThreads; i++) {
pthread_join(workerThreads[i], NULL);
}
timeTaken = timestamp() - timeTaken;
printf("Total time taken = %f\n", timeTaken);
/*printf("The results are\n");
for(i=0; i<numberOfThreads; i++) {
printf("%d\n",result[i]);
}*/
free(array);
exit(0);
}