2016-06-22 6 views
1

次のコードを記述しました。私がシングルスレッド(コードでaa = 1)を使用している場合、11秒かかります。しかし、aa = 2の場合、190秒かかる。私のマシンは4CPUです。親切に私を助けてくれますか?私は提案に基づき-032つ以上のスレッドを使用する場合、Cでのマルチスレッドプログラミングが遅い

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



#define N 100 

int aa; 


unsigned long long *reg, *b; 
#define LIMIT 5000000 




void *abc(void* arg){ 
     srand(time(NULL)); 

     unsigned long long i,l; 
     unsigned char z,j; 
     int *limit_ptr=(int *)arg; 
     int i1=*limit_ptr; 
     printf("i1=%d\n",i1); 
     for(l=0;l<LIMIT;l++){ 
      for(i=0;i<N;i++) 
       z=(((double) N)*rand()/(RAND_MAX+1.0));; 

      z = (((double) N)*rand()/(RAND_MAX+1.0));; 

      if(z==0) 
       reg[i1]++; 

     }   

} 

int main(){ 

    int l; 
    aa=2; 
    printf("%d \n\n",aa); 
    reg = (unsigned long long *) malloc(aa * sizeof(unsigned long long)); 
    b = (unsigned long long *) malloc(aa * sizeof(unsigned long long)); 

    struct timespec start, finish; 
    double elapsed; 
    clock_gettime(CLOCK_MONOTONIC, &start); 

    for(l=0;l<aa;l++) 
     reg[l]=0; 
    pthread_t tid[aa]; 

    int j1; 
    unsigned long long cc=0; 



    for(j1=0;j1<aa;j1++) 
     b[j1]=j1; 


    for(j1=0;j1<aa;j1++){ 

     printf("%d\n", j1); 
     pthread_create(&tid[j1],NULL,abc,&b[j1]); 
    } 
//  

    for(j1=0;j1<aa;j1++){ 
     pthread_join(tid[j1],NULL); 
     printf("%d\n", j1); 
    } 

    for(j1=0;j1<aa;j1++)  
     cc=cc+reg[j1]; 


    printf("%0.10f %llu\n", (double)cc/(aa*LIMIT),cc); 

    clock_gettime(CLOCK_MONOTONIC, &finish); 
    elapsed = (finish.tv_sec - start.tv_sec); 
    elapsed += (finish.tv_nsec - start.tv_nsec)/1000000000.0; 

    printf("Time=%0.10f\n", elapsed); 
    pthread_exit(NULL); 

} 

を-lpthread Thread.c

gccのようにコンパイルしています、私は、コードを変更しました。実行時間は今は大丈夫ですが、乱数の生成はうまくいきません。コード内の配列regの値は同じです。私を助けてください。私はこれでEOFに同意する必要が

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


#define N 100 
#define aa 4 



unsigned long long *reg, *b; 
#define LIMIT 5000000 

int rgen() 
{ 
    int xi; 
    int seed; 
    struct drand48_data drand_buf; 
    double x; 
    static i; 

    if (i==0){ 
     seed = time(NULL); 
     srand48_r(seed, &drand_buf); 
     i = 10; 
    } 

    drand48_r (&drand_buf, &x); 
    xi = (int) (x * 100);  

    return xi; 
} 


void *abc(void* arg){ 
     int l,i, z; 
     int *limit_ptr = (int *) arg; 
     int i1 = *limit_ptr; 

     printf("i1=%d\n",i1); 
     for(l=0; l<LIMIT; l++){ 
       for(i=0; i<N; i++) 
        z= rgen(i1); 

      if(z==0) 
       reg[i1]++; 

     }   

} 

int main(){ 

int l; 

printf("%d \n\n",aa); 
reg = (unsigned long long *) malloc(aa * sizeof(unsigned long long)); 
b = (unsigned long long *) malloc(aa * sizeof(unsigned long long)); 

struct timespec start, finish; 
double elapsed; 
clock_gettime(CLOCK_MONOTONIC, &start); 

for(l=0;l<aa;l++) 
    reg[l]=0; 
pthread_t tid[aa]; 

int j1; 
unsigned long long cc=0; 



for(j1=0;j1<aa;j1++) 
    b[j1]=j1; 


for(j1=0;j1<aa;j1++){ 

    printf("%d\n", j1); 
    pthread_create(&tid[j1],NULL,abc,&b[j1]); 
} 
//  
    printf("created threads\n"); 
    for(j1=0;j1<aa;j1++){ 
    pthread_join(tid[j1],NULL); 
    printf("%d\n", j1); 
    } 

for(j1=0;j1<aa;j1++)  
    cc=cc+reg[j1]; 

printf("\n"); 
for(j1=0;j1<aa;j1++) 
    printf("%llu ", reg[j1]); 

printf("\n"); 

printf("%0.10f %llu\n", (double)cc/(aa*LIMIT),cc); 

clock_gettime(CLOCK_MONOTONIC, &finish); 
elapsed = (finish.tv_sec - start.tv_sec); 
elapsed += (finish.tv_nsec - start.tv_nsec)/1000000000.0; 

printf("Time=%0.10f\n", elapsed); 
pthread_exit(NULL); 


} 
+0

1) 'malloc()'の結果をキャストしない 2)あなたの 'malloc()'呼び出しの戻り値を決してテストしない – KevinDTimm

+0

また、あなたのコードは、ほとんどの時間を費やしている場所を見つけることができます。 – KevinDTimm

+1

Havは、 'abc()'のループがaa = 1とaa = 2(どのスレッドでも)一緒に横断されている頻度を数えましたか?いったん持っていたら、戻って質問を修正してください。ヒント:あなたのスレッドは何も共有していません – tofro

答えて

1

:問題はrand()への呼び出しです。彼らがtime(NULL)に置き換えられた場合、あなたはあなたが期待するものを得るでしょう。

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

#define N 100 
#define LIMIT 5000000 

static unsigned long long *reg; 

void *abc(void *arg) 
{ 
    //srand(time(NULL)); 
    unsigned long long i, l, k; 
    unsigned char z; 
    int *limit_ptr = (int *) arg; 
    int i1 = *limit_ptr; 

    printf("Argument: i1=%d\n", i1); 
    k = 0; 

    for (l = 0; l < LIMIT; l++) { 
    for (i = 0; i < N; i++){ 
     z = (((double) N) * time(NULL)/(RAND_MAX + 1.0)); 
     k++; 
    } 
    z = (((double) N) * time(NULL)/(RAND_MAX + 1.0)); 
    if (z == 0) 
     reg[i1]++; 
    } 
    printf("Loops of %d: %lld\n",i1, k); 
    // normal would be pthread_exit() but the linear timings would need 
    // their own function/ extra argument/needless complexity 
    return NULL; 
} 

int main(int argc, char **argv) 
{ 
    int l; 

    struct timespec start, finish; 
    double elapsed_threaded, elapsed_linear; 

    int j1; 
    unsigned long long cc = 0; 

    int num_threads; 

    unsigned long long *b; 

    pthread_attr_t attr; 

    if(argc > 1) 
    num_threads = atoi(argv[1]); // don't use atoi in production 
    else 
    num_threads = 2; 

    printf("# of threads: %d\n", num_threads); 
    // checks omitted here 
    reg = (unsigned long long *) malloc(num_threads * sizeof(unsigned long long)); 
    b = (unsigned long long *) malloc(num_threads * sizeof(unsigned long long)); 

    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 

    for (l = 0; l < num_threads; l++) 
    reg[l] = 0; 
    pthread_t tid[num_threads]; 

    for (j1 = 0; j1 < num_threads; j1++) 
    b[j1] = j1; 

    clock_gettime(CLOCK_MONOTONIC, &start); 
    for (j1 = 0; j1 < num_threads; j1++) { 
    printf("Thread #%d started\n", j1); 
    // Check omitted 
    pthread_create(&tid[j1], &attr, abc, &b[j1]); 
    } 
    for (j1 = 0; j1 < num_threads; j1++) { 
    // Check omitted 
    pthread_join(tid[j1], NULL); 
    printf("Thread #%d joined\n", j1); 
    } 
    clock_gettime(CLOCK_MONOTONIC, &finish); 

    for (j1 = 0; j1 < num_threads; j1++) 
    cc = cc + reg[j1]; 

    printf("%0.10f %llu\n", (double) cc/(num_threads * LIMIT), cc); 

    elapsed_threaded = (finish.tv_sec - start.tv_sec); 
    elapsed_threaded += (finish.tv_nsec - start.tv_nsec)/1000000000.0; 

    clock_gettime(CLOCK_MONOTONIC, &start); 
    for (j1 = 0; j1 < num_threads; j1++) { 
    abc(&b[j1]); 
    } 
    clock_gettime(CLOCK_MONOTONIC, &finish); 
    elapsed_linear = (finish.tv_sec - start.tv_sec); 
    elapsed_linear += (finish.tv_nsec - start.tv_nsec)/1000000000.0; 

    printf("Time threaded: %0.10f\nTime linear: %0.10f\nRelation %0.10f\n", 
      elapsed_threaded,elapsed_linear, elapsed_threaded/elapsed_linear); 
    pthread_exit(NULL); 
} 

私は少しそれをクリーンアップ(明示的にPTHREAD_CREATE_JOINABLEを設定すると、おそらく冗長ですが、確かにpthreadのの実装を確認してください)。あなたは私のCPUを持っている今、どのように多くのコアを推測することがあり

1 thread: 
Time threaded: 1.3713400890 
Time linear: 1.3394284740 
Relation 1.0238247996 

2 threads: 
Time threaded: 1.4989349930 
Time linear: 2.6568704750 
Relation 0.5641731530 

3 threads: 
Time threaded: 1.8101585490 
Time linear: 3.9965480710 
Relation 0.4529305082 

4 threads: 
Time threaded: 1.3974386710 
Time linear: 5.3152423440 
Relation 0.2629115627 

5 threads: 
Time threaded: 1.7717215210 
Time linear: 6.6438871330 
Relation 0.2666694189 

gcc -W -Wall -O3 -g3 thread.c -o thread -lpthread

結果でコンパイル

PS:あなたが実験している場合は、特に、実験している場合でも、すべてチェックを実施してください。

+0

ありがとうございます。しかし(((ダブル)N)*時間(NULL)/(RAND_MAX + 1.0))はランダムな値を与えていません。 – user12290

+0

@ user12290これはスレッドセーフの問題を示すためのものです。 'rand(3)'のスレッドセーフなバリアントは 'rand_r(3)'ですが、Posix-2008以降では廃止されていますので、 '[delnmj] rand48_r(3)'またはroll-your-ownのいずれかです。 – deamentiaemundi

関連する問題