2017-05-03 9 views
0
int run_me(unsigned long prime, unsigned long max, int *ary) { 
    unsigned long i; 
    printf("\nI am %d", prime); 

    if(prime > sqrt(max)) { 
    return 1; /* do no run */ 
    } 

    for(i = 3; i*prime < max; i+=2) { 
    ary[i*prime - 1] = 1; 
    } 

    return 0; 
} 

typedef struct Args { 
    unsigned long max, prime; 
    int *ary; 
} args; 

void *thread_runner(void *all_args) { 
    args *my_args = all_args; 
    run_me(my_args->prime, my_args->max, my_args->ary); 
    return 0; 
} 

unsigned long *sieve_of_eratosthenes(unsigned long begin, unsigned long end) { 
    unsigned long i, j, arylen, *ary_to_ret; 
    unsigned long current_primes[4] = {3, 5, 7, 11}; /* holds primes being used by threads*/ 
    int *ary_of_all; 
    pthread_t threads[4]; 
    args *curr; 

    curr = malloc(sizeof(args)); 

    ary_of_all = calloc(end, sizeof(int)); 
    arylen = end - begin + 2; 
    ary_to_ret = calloc(arylen, sizeof(unsigned long)); 
    ary_of_all[0] = 1; 

    /*mark all even numbers*/ 
    for(i = 1; 2 * i < end; i++) { 
    ary_of_all[2*i - 1] = 1; 
    } 

    while(current_primes[3] < sqrt(end)) { 
     /*run threads with current primes*/ 
    for(i = 0; i < 4; i++) { 
     curr->prime = current_primes[i]; 
     curr->max = end; 
     curr->ary = ary_of_all; 
     pthread_create(&threads[i], NULL, thread_runner, curr); 
    } 
    /* join all threads */ 
    for(i = 0; i < 4; i++) { 
     pthread_join(threads[i], NULL); 
    } 

    j = 0; /* number of primes found */ 

    /*find new primes*/ 
    for(i = current_primes[3] + 2; i < end && j < 4; i+=2) { 
     if(ary_of_all[i - 1] == 0) { 
     current_primes[j] = i; 
     j++; 
     } 
    } 

    } 

    /*run threads one more time*/ 
    if(current_primes[0] <= sqrt(end)) { 
    for(i = 0; i < 4; i++) { 
     curr->prime = current_primes[i]; 
     curr->max = end; 
     curr->ary = ary_of_all; 
     pthread_create(&threads[i], NULL, thread_runner, curr); 
    } 
    /* join all threads */ 
    for(i = 0; i < 4; i++) { 
     pthread_join(threads[i], NULL); 
    } 
    } 

    /*create the array to be returned*/ 
    j = 0; /*pos in *ary_to_ret*/ 
    for(i = begin; i <= end; i++) { 
    if(ary_of_all[i-1] == 0) { 
     ary_to_ret[j] = i; 
     j++; 
    } 

    } 

    ary_to_ret[j] = 0; /* null terminate */ 
    ary_to_ret = realloc(ary_to_ret, (j+1) * sizeof(unsigned long)); 
    return ary_to_ret; 
} 

私は上記のコードを実行して、Sag of Eratosthenesを使用して高い値と低い値を与えられた素数のリストを取得しています。私はコードが主に動作しますが、このコードを実行すると、curr_primes配列の最初の要素を使用して作成したスレッドは使用されず、代わりに5,7,11,11が実行されます。配列を実行するたびにこれを行いますそれを再増殖させる。私は誰かが私にこのように動作する理由を説明できるかどうか疑問に思っていました。最初のスレッドは与えられた引数で実行されていません

+1

これは迷惑であることを意味しMCVE([MCVE])、ではありません - 私たちは ''メイン()を書くために仕事をしてなくて、コードを実行し、提供することはできませんヘッダーなど。MCVEを提供すると、 '。/ program'のように単純ではない場合に実行する方法についての指示があれば、より早く回答が得られます。あなたはまたあなたが得る出力を示すかもしれません。私は出力が改行で終わらないデバッグ印刷を信頼しません。つまり、 'printf(" \ nI%d "、プライム);'私が関係する限り間違っています。 printf( "私は%d \ n"、素数);またはおそらく 'printf(" \ n私は%d \ n "、素数);' - キーは改行で終わる出力です。 –

答えて

1

同じcurrをすべてのスレッドに渡しています。あなたはそれが巨大な競争状態であることを観察しただけでなく、うまく動作することは幸運です。代わりに、コードは別のargバッファを各スレッドに渡す必要があります。ここでは一例です:

/* doesn't really need to be dynamic memory in this simple example */ 
args curr[4]; 

for(i = 0; i < 4; i++) { 
    curr[i].prime = current_primes[i]; 
    curr[i].max = end; 
    curr[i].ary = ary_of_all; 
    pthread_create(&threads[i], NULL, thread_runner, &curr[i]); 
} 

/* join all threads */ 
for(i = 0; i < 4; i++) { 
    pthread_join(threads[i], NULL); 
} 
+0

ありがとう、それは多くの意味があります。何故それが一貫していたのか分かりますか? –

+0

@KevinPostlethwaitタイミングに依存し、実行するたびにチャンスがあるため、タイミングは比較的似ています。しかし、それは決して保証ではありません。負荷が高くなったり、別のコンパイラでコンパイルしたり、別のシステムで実行したり、環境やコードに無関係な変更があったりすると、動作が変わる可能性があります。これはCの未定義ビヘイビアーの定義です。 – kaylum

関連する問題