C 如何并行斐波那契序列直到10^5项

C 如何并行斐波那契序列直到10^5项,c,multithreading,parallel-processing,openmp,fibonacci,C,Multithreading,Parallel Processing,Openmp,Fibonacci,我需要(用openmp)从这个序列代码中并行斐波那契序列来计算序列的第105项,但是我已经被困了3周,没有任何好的想法,有人有什么好的方法来做吗 以下是C语言中的顺序代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100010 #define LEN 25001 char seq[MAX][LEN]; void add(int a, int b) {

我需要(用openmp)从这个序列代码中并行斐波那契序列来计算序列的第105项,但是我已经被困了3周,没有任何好的想法,有人有什么好的方法来做吗

以下是C语言中的顺序代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 100010
#define LEN 25001

char seq[MAX][LEN];

void add(int a, int b) {
    int i, aux, s;

    for (i = 0, aux = 0; seq[a][i] != '\0' && seq[b][i] != '\0'; i++) {
        s = seq[a][i] + seq[b][i] + aux - '0' - '0';
        aux = s / 10;
        seq[a + 1][i] = s % 10 + '0';
    }

    while (seq[a][i] != '\0') {
        s = seq[a][i] + aux - '0';
        aux = s / 10;
        seq[a + 1][i] = s % 10 + '0';
        i++;
    }

    while (seq[b][i] != '\0') {
        s = seq[b][i] + aux - '0';
        aux = s / 10;
        seq[a + 1][i] = s % 10 + '0';
        i++;
    }

    if (aux != 0)
        seq[a + 1][i++] = aux + '0';

    seq[a + 1][i] = '\0';
}

int main() {
    int n, i, len;

    seq[0][0] = '0';
    seq[0][1] = '\0';
    seq[1][0] = '1';
    seq[1][1] = '\0';

    for (i = 2; i < MAX; i++)
        add(i - 1, i - 2);

    scanf("%d", &n);

    len = strlen(seq[n]);
    for (i = 0; i <= len - 1; i++)
        printf("%c", seq[n][len - 1 - i]);
    printf("\n");
    fflush(stdout);

    return 0;
}
#包括
#包括
#包括
#定义最大值100010
#定义LEN 25001
字符顺序[最大值][长度];
无效添加(内部a、内部b){
int i、aux、s;
对于(i=0,aux=0;seq[a][i]!='\0'和&seq[b][i]!='\0';i++){
s=序号[a][i]+序号[b][i]+辅助符号-“0”-“0”;
aux=s/10;
序号[a+1][i]=s%10+'0';
}
而(seq[a][i]!='\0'){
s=序号[a][i]+辅助项-“0”;
aux=s/10;
序号[a+1][i]=s%10+'0';
i++;
}
而(seq[b][i]!='\0'){
s=序号[b][i]+辅助项-“0”;
aux=s/10;
序号[a+1][i]=s%10+'0';
i++;
}
如果(aux!=0)
序号[a+1][i++]=aux+'0';
序号[a+1][i]='\0';
}
int main(){
int n,i,len;
seq[0][0]=“0”;
seq[0][1]='\0';
序号[1][0]=“1”;
seq[1][1]='\0';
对于(i=2;i
以下是我的提示:

您有两个数,长度为多(千)位数,处理器为N。您可以将加法拆分为多个线程。例如:

F(167) == 35600075545958458963222876581316753
F(168) == 57602132235424755886206198685365216
要计算F(169),你必须把上面两个数字相加,但我们把它看作4个独立的加法,每个加法9位

          (A)         (B)         (C)        (D)
F(167) == 035600075   545958458   963222876  581316753
F(168) == 057602132   235424755   886206198  685365216
======================================================= + 
           93202207   781383213  1849429074 1266681969
                                 ^          ^
现在我们有4个求和。其中两个,
C
D
,有一个进位运算。所以我们只需要将每一个的左边的结果调整+1

           93202207   781383213   849429074  266681969
                             +1          +1
======================================================= + 
F(169) ==  93202207   781383214   849429075 266681969
因此,计算Fib(100000)的算法如下所示。其中,
BigNumber
是一个表示数字的结构。您使用的是字符数组,这也是可以接受的

void fib(int stop)
{
    BigNumber  f0 = 0;
    BigNumber  f1 = 1;
    BigNumber  f2 = 1;

    BigNumber* pF0 = &f0;
    BigNumber* pF1 = &f1;
    BigNumber* pF2 = &f2;

    for (int i = 2; i <= stop; i++)
    {
        ParallelAdd(pF0, pF1, pF2); // *pF2 = *pF1 + *pF0

        // shift via pointers
        pF0 = pF1;
        pF1 = pF2;
        pF2 = pF0;
    }
    Print(f2);
}

main()
{
    fib(100000);
}
void fib(整站)
{
BigNumber f0=0;
大数f1=1;
大数f2=1;
BigNumber*pF0=&f0;
BigNumber*pF1=&f1;
BigNumber*pF2=&f2;

对于(int i=2;i而不是尝试并行化bignum加法(这很棘手),您可以尝试并行计算多个项:

F(n+1) = F(n) + F(n-1)
F(n+2) = F(n+1) + F(n) = 2*F(n) + F(n-1)
F(n+3) = F(n+2) + F(n+1) = 2*F(n+1) + F(n) = 2*F(n) + 2*F(n-1) + F(n) = 3*F(n) + 2*F(n-1)
...
还请注意,您应该一次计算数字块:可以使用32位数组元素计算8或9个以10为基数的数字

以下是经过多次改进的修改版本:

  • 它一次计算8位数的块
  • 它可以接受命令行参数
  • 它使用更少的内存
  • 它可以处理更大的值
  • 它的效率更高(20倍)
您应该能够轻松地将其并行化

/*通过chqrlie的可并行bignum-Fibonacci计算*/
#包括
#包括
#包括
#包括
#包括
#如果0
/*fib为2500ms(100000)*/
#定义数字10
#定义NDIGIT 1
#定义FMT“d”
typedef无符号字符数字\u t;
#elif 1
/*fib为279ms(100000)*/
#定义数字100000000
#定义ndigit8
#定义FMT优先级32
typedef uint32位;
#否则
/*fib为720ms(100000)*/
#定义数字10000000000000000000000
#定义NDIGIT 18
#定义FMT优先级64
typedef uint64位;
#恩迪夫
内部地址1(数字\u t*c、常量数字\u t*a、常量alen、常量数字\u t*b、常量blen){
数字辅助;
int i;
/*假设alen>=blen*/
对于(i=0,aux=0;i=blen*/
对于(i=0,aux=0;i=blen*/
对于(i=0,aux=0;i=blen*/
对于(i=0,aux=0;i1){
MAX=MIN=strtol(argv[1],NULL,0);
如果(argc>2)
MAX=strtol(argv[2],NULL,0);
}否则{
扫描频率(“%d”和最小值);
最大值=最小值;
}
/*如果fib(n)小于n*log10(φ)+2,则长度*/
LEN=(最大*20910ULL)/100000/NDIGIT+2;
/*分配8个bignum*/
int*slen=calloc(sizeof(*slen),8);
数字(*序号)[LEN]=calloc(sizeof(*序号),8;
if(slen==NULL | | seq==NULL){
fprintf(stderr,“内存分配错误”);
返回1;
}
seq[0][0]=0;
slen[0]=1;
如果(0>=MIN)printseq(seq[0],slen[0]);
序号[1][0]=1;
slen[1]=1;
如果(1>=MIN)printseq(seq[1],slen[1]);
对于(i=2;i=MIN)printseq(seq[i],slen[i]);
}
对于(;i=MIN)printseq(seq[i0],slen[i0]);
如果(i+1>=MIN)printseq(seq[i1],slen[i1]);
如果(i+2>=MIN)优先级