基于OpenMP实现利用泰勒级数计算正弦函数sin(x)的并行程序

一、正弦函数的泰勒级数

sin(x) = x - \frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\cdots=\sum_{i=0}^{\infty}(-1)^i\frac{x^{2i+1}}{(2i+1)!}

基于此泰勒级数,完成正弦函数sin(x)计算程序,并在多核系统中,比较不同线程个数与串行程序的运行时间。

二、程序设计

1.串行程序

并行程序的基础是串行程序,我们先实现一个简单的利用泰勒级数计算正弦函数的程序:

#include <stdio.h>
#include <math.h>
#define pi 3.1415926

int main(){

    int i=1,count=0;
    double x=pi/3;
    double sum,term;
    
    // printf("Input x: ");
    // scanf("%f",&x);
    sum=x;   //赋初始值
    term=x;

    for(i;i<10;i+=2){
        term =-term*x*x/((i+1)*(i+2));//计算相应项
        // printf("%f\n",term);
        sum+=term;
        count++;
    }
    printf("sin(%f)=%f,count=%d\n",x,sum,count);
    return 0;
}

程序结果为:

基于此程序,我们才可以开展并行程序设计。

2.并行程序

观察泰勒级数,发现每一次计算第i个数时,我们都是对第i-1个数直接进行操作以简化阶乘、次方的运算,即后续计算结果强依赖于前面的计算结果,这与阶乘的并行化有异曲同工之妙。

那么现在我们只需固定计算总次数(for循环次数)为MAXC,按线程数量NUM_THREADS对MAXC进行切分,让每一个线程都对不同的i从1开始计算,最终我们会得到线程数量个数的计算偏移量(offset1、offset2、...),将这些偏移量按顺序相乘,便可以得到该线程对应第i块的级数:

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <time.h>
#include <math.h>
#define pi 3.1415926
#define MAXC 1000000000
#define NUM_THREADS 16

int main(){
    double x;
    x=pi/3;
    // printf("Input x: ");
    // scanf("%lf",&x);

    while(x>pi){
        x-=pi;
    }
    while(x<-pi){
        x+=pi;
    }
    int i=1;
    double sum=0,term;
    double mid[NUM_THREADS+1];//offset for every threads
    mid[0]=x;
    
    // Start measuring time
    clock_t start = clock();
    #pragma omp parallel num_threads(NUM_THREADS) shared(mid,sum) private(term)
    {
        int itd = omp_get_thread_num();
        int ntd = omp_get_num_threads();
        int jud=1;
        double midsum=0;
        double offset=1.0;
        term=1;

        #pragma omp for schedule(static) private(i)
        for(i=1;i<MAXC;i++){
            jud=(i%2==0)?1:-1;
            term=(term<0)?-term:term;
            term =(double)jud*term*x*x/(double)((2*i)*(2*i+1));
            midsum+=term;
        }
        mid[itd+1]=term;

        #pragma omp barrier
        for(i=0;i<(itd+1);i++){
            offset*=mid[i];
        }
        midsum*=offset;

        #pragma omp critial
        sum+=midsum;
    }
    // Stop measuring time and calculate the elapsed time
    clock_t end = clock();
    double elapsed = (double)(end - start)/CLOCKS_PER_SEC;
    printf("sin(%f)=%f\n",x,sum+x);
    printf("用时: %.3f 秒\n", elapsed);

    return 0;
}

三、程序结果

设置线程数量分别为16、1、8,运行后结果如下:

可以发现并行程序大大减少了串行程序的运行时间。

参考:

C语言利用泰勒级数sin(X)_求泰勒级数的c语言-CSDN博客

c - Parallelizing Factorial Calculation - Stack Overflow

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值