2017-05-03 53 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; 
} 

我正在运行上面的代码,以获得使用Eratosthenes筛选获得高和低值的素数列表。我的代码大部分工作,但是当我运行此代码,我创建使用我curr_primes数组的第一个元素的线程永远不会使用,而是运行5,7,11,11,为此,它会在每次通过阵列运行时间并重新填充它。我想知道是否有人可以向我解释为什么它以这种方式运行。第一个线程没有运行给定的参数

+1

这不是一个MCVE([MCVE]),这意味着它是一个滋扰 - 不能没有做功运行的代码写一个主'()'和提供头文件等等。如果你提供了一个MCVE,你将会得到更快的答案 - 如果它不像'。/ program'那么简单,那么你将得到如何运行它的指令。你也可以显示你得到的输出。我不信任输出不以换行符结束的调试打印。这意味着'printf(“\ n我是%d”,prime);'就我而言是错误的;它应该是'的printf( “我是%d \ n”,素数);'或'可能的printf( “\ NI上午%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

相关问题