2013-11-21 134 views
0

我有一个简单的问题给你。我使这个代码来计算一个数字的阶乘而不递归。非递归阶乘C

int fact2(int n){ 
    int aux=1, total = 1; 
    int i; 
    int limit = n - 1; 
    for (i=1; i<=limit; i+=2){ 
     aux = i*(i+1); 
     total = total*aux; 
    } 
    for (;i<=n;i++){ 
     total = total*i; 
    } 
return total; 

} 

正如您所看到的,我的代码使用循环展开来优化执行中的时钟周期。现在我被要求为相同的代码添加双向并行性,任何想法如何?

+0

n! = n *(n-1)* ... *(n/2)* ... * 1.您可以让一个CPU执行前n/2次乘法,另一个CPU执行其余的运算,然后乘以2次结果一起。 –

回答

2

您可以使用ptherads库创建两个单独的线程。每个线程应该执行一半的乘法。我可以把解决方案放在一起。

#include <pthread.h> 

typedef struct { 
    int id; 
    int num; 
    int *result; 
} thread_arg_t; 

void* thread_func(void *arg) { 
    int i; 
    thread_arg_t *th_arg = (thread_arg_t *)arg; 
    int start, end; 
    if(th_arg->id == 0) { 
     start = 1; 
     end = th_arg->num/2; 
    } else if (th_arg->id == 1) { 
     start = th_arg->num/2; 
     end = th_arg->num + 1; 
    } else { 
     return NULL; 
    } 
    for(i=start; i < end; i++) { 
      th_arg->result[th_arg->id] *= i; 
    } 
    return NULL; 
} 

int factorial2(int n) { 
    pthread_t threads[2]; 
    int rc; 
    int result[2]; 
    thread_arg_t th_arg[2]; 
    for(i=0; i<2; i++) { 
     th_arg[i].id = i; 
     th_arg[i].num = n; 
     th_arg[i].result = result; 
     rc = pthread_create(&threads[i], NULL, thread_func, (void *)&th_arg[i]); 
     if (rc){ 
     printf("pthread_create() failed, rc = %d\n", rc); 
     exit(1); 
     } 
    } 

    /* wait for threads to finish */ 
    for(i=0; i<2; i++) { 
     pthread_join(thread[i], NULL); 

    /* compute final one multiplication */ 
    return (result[0] * result[1]); 
} 

pthread库实现应该负责为您并行处理两个线程的工作。而且,这个例子可以通过微小的修改来推广到N个线程。

+0

比普通的旧顺序解决方案慢多少?这不是你的错,但你可以在阶乘上做的乘法运算的次数不会溢出简单的'int'大约是12(包括乘以1),创建和销毁线程的开销相比而言是天文数字。对于64位“int”类型,范围上升到20;仍然不足以抵消线程创建的成本。 –

+0

你是对的,对于整数乘法,并行化可能没有任何改进。如何浮点大小写? –

+0

请参阅[Amdahl's Law](http://en.wikipedia.org/wiki/Amdahl's_law)的一些解释。线程设置(和拆卸)的开销不可忽略,所以线程必须做的值得创建的计算量也很可观。如果你正在使用一个确切的“大数”算术包并计算N!对于数百个N的值,那么你会获得一些好处。对于浮点算术,如果你有足够大的N值,你可能会看到一些好处,但是我怀疑你不会看到任何好处;计算根本不够重。 –