2013-11-21 5 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. 첫 번째 n/2 곱셈을 한 CPU가 수행 할 수 있고 나머지 CPU가 나머지 CPU를 수행 한 다음 두 결과를 곱합니다 함께. –

답변

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 값이 충분히 크면 몇 가지 이점을 얻을 수 있지만 이점이 보이지 않는다고 의심됩니다. 계산은 단순히 충분히 무겁지 않습니다. –