【问题标题】:OpenMP paralleling GSL Ordinary Differential Equations calculationOpenMP 并行 GSL 常微分方程计算
【发布时间】:2019-10-10 17:02:57
【问题描述】:

我正在尝试并行化我的代码,但出现了错误。我需要计算一个 Cauchy 问题(它已经完成),但我需要使用 OpenMP lib 并行化它。

我尝试使用 OpenMP 编写一些代码,但它不起作用。

我创建了一个结构来收集结果。

struct Dots {
    double par;
    double x;
    double y;
};

这是我的带参数的目标函数。

int ode_func (double x, const double y[], double f[], void *params)
{

    double mu = *(int *)params;
    f[0] = x + 2 * y[0] / (1 + mu * mu);
    return GSL_SUCCESS;
}

这是主要功能。我目前没有找到如何创建struct数组的方法,但这不是主要问题。

void calc_cauchy_problem(struct Dots ArrayOfDots[], double x_start, double x_end, double y_start,
        int count) {

    int dim = 1;
    double x = x_start;
    double y[1] = {y_start};
    int mu = 5;
    int param = 0;
    gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
    gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
                                                               gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
    int status = 0;
#pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status)
    for (int param = 1; param < mu; param++) {

        gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
        gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
                                                               gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
        for (int i = 1; i <= count; i++)
        {
            double xi = x_start + i * (x_end - x_start) / count;

            int status = gsl_odeiv2_driver_apply(d, &x, xi, y);

            if (status != GSL_SUCCESS)
            {
                printf ("error, return value=%d\n", status);
                break;
            }
           // ArrayOfDots[i].par = mu;
           // ArrayOfDots[i].x = xi;
           // ArrayOfDots[i].y = y[0];
        }
        gsl_odeiv2_driver_free (d);
    }

}

主要

int main() {
    double x_start = 0;
    double x_end = 10;
    double y_start = 0;
    int count = 10;
    struct Dots ArrayOfDots[count];
    calc_cauchy_problem(ArrayOfDots, x_start, x_end, y_start, count);
    return 0;
}

使用gcc main.c -o main -fopenmp -lgsl -std=gnu11 编译成功,但是当我启动它时出现错误

gsl: driver.c:354: ERROR: integration limits and/or step direction not consistent
Default GSL error handler invoked.

我认为这是#pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status) 的主要问题,但我不知道如何以另一种方式重写它。 感谢您的回复。

更新:

在 Kaveh Vahedipour 的帮助下,我的代码部分开始工作。这意味着我的 for 循环的一半开始工作。 升级版升级版: 经过另一次调查,我有以下代码: 它已编译并运行,但我得到了 Process finished with exit code 4printf("Elapsed time = %f\n", omp_get_wtime() - start_time); 不打印任何内容。

struct Dots {
    double par;
    double x;
    double y;
};

int ode_func (double x, const double y[], double f[], void *params)
{

    double mu = *(int *)params;
    f[0] = (x + 2 * y[0]) / (1 + mu * mu);
    return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
                         int count, int param1, int param2) {
    int dim = 1;
    double x = x_start;
    double y[1] = {y_start};
    int param = param1;
    int j = 0;
    int status = 0;
    char filename[10];

#pragma omp parallel for private(param, status, x, y)
    for (param = param1; param <= param2; param++) {
        struct Dots ArrayOfDots[count];
        gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
        gsl_odeiv2_driver * d =
                gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
        for (int i = 1; i <= count; i++) {
            double xi = x_start + i * (x_end - x_start) / count;

            int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
            if (status != GSL_SUCCESS)
            {
                printf ("error, return value=%d\n", status);
                break;
            }

            ArrayOfDots[i].par = param;
            ArrayOfDots[i].x = xi;
            ArrayOfDots[i].y = y[0];
        }
        gsl_odeiv2_driver_free (d);

    }
}
int main() {
    double start_time = omp_get_wtime();
    double x_start = 0;
    double x_end = 10;
    double y_start = 0;
    const int count = 500;
    int param1 = 1;
    int param2 = 10;
    calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
    printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
    return 0;
}

【问题讨论】:

  • 如果您也可以发布主要内容:)
  • 是的,我已经更新了。
  • 无法再编译。 main 不适合新的柯西问题。请更新所有代码,以便再次编译。
  • 做到了。检查一下。
  • 看看下面我将 ArrayOfDots 放入循环中的意思

标签: c openmp gsl


【解决方案1】:

x 添加到私有循环变量:private(sys, param, d, status, x)。如果您仍然遇到问题,请回复我。

void calc_cauchy_problem(double x_start, double x_end, double y_start,
                         int count, int param1, int param2) {

  int dim = 1;
  double x = x_start;
  double y[1] = {y_start};
  int param = param1;
  int j = 0;
  int status = 0;
  char filename[10];

#pragma omp parallel for private(param, status, x, y)
  for (param = param1; param <= param2; param++) {
    struct Dots ArrayOfDots[count];
    gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
    gsl_odeiv2_driver * d =
      gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
    for (int i = 1; i <= count; i++) {
      double xi = x_start + i * (x_end - x_start) / count;

      int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
      if (status != GSL_SUCCESS)
        {
          printf ("error, return value=%d\n", status);
          break;
        }
      ArrayOfDots[i].par = param;
      ArrayOfDots[i].x = xi;
      ArrayOfDots[i].y = y[0];
    }
    //write_data_to_file(param, count, ArrayOfDots);                                                                                        
    for (int i = 0; i < count; ++i) {
      printf ("%d: %f, %f, %f\n", omp_get_thread_num(),
              ArrayOfDots[i].par, ArrayOfDots[i].x, ArrayOfDots[i].y);
    }
    gsl_odeiv2_driver_free (d);
  }
}

【讨论】:

  • Kaveh,这似乎对我没有帮助。我又遇到了这个错误。 gsl:driver.c:354:错误:集成限制和/或步进方向不一致调用了默认的 GSL 错误处理程序。我是通过增加参数 mu 得到的。
  • 稍后会调查。现在和我的孩子一起徒步旅行
  • 哦,Kaveh,我太不专心了。这个由我引起的新问题——我没有在 pragma omp parallel 中写“for”。现在它可以部分工作了。
  • 太棒了。如果您接受答案,仍然会很感激。 :)
  • 如果它对我有部分帮助,我可以接受吗? :) 现在我有一个问题,我只有一半的数据。另一半因先前的错误而下降。
【解决方案2】:

似乎这个版本运行良好。我认为问题出在这个结构Dots ArrayOfDots[count]; 上,当我尝试将值推送到这个结构时。

      ArrayOfDots[i].par = param;
      ArrayOfDots[i].x = xi;
      ArrayOfDots[i].y = y[0];

这是完整的代码。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// GSL lib includes
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>


int ode_func (double x, const double y[], double f[], void *params)
{

    double mu = *(int *)params;
    f[0] = (x + 2 * y[0]) / (1 + mu * mu);
    return GSL_SUCCESS;
}

void calc_cauchy_problem(double x_start, double x_end, double y_start,
                         int count, int param1, int param2) {

#pragma omp parallel for
    for(int param = param1; param < param2; param++) {
        gsl_odeiv2_system sys = {ode_func, NULL, 1, &param};

        gsl_odeiv2_driver * d =
                gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd,
                                               1e-6, 1e-6, 0.0);
        int i;
        double x = x_start, x1 = x_end;
        double y[1] = { y_start };

        for (i = 1; i <= count; i++)
        {
            double xi = i * x1 / count;
            int status = gsl_odeiv2_driver_apply (d, &x, xi, y);

            if (status != GSL_SUCCESS)
            {
                printf ("error, return value=%d\n", status);
                break;
            }

//            printf ("%d %d %.5e %.5e\n", omp_get_thread_num(), param, x, y[0]);
        }

        gsl_odeiv2_driver_free (d);
        }
    }

int main() {
    double start_time = omp_get_wtime();
    double x_start = 0;
    double x_end = 10;
    double y_start = 0;
    const int count = 100000;
    int param1 = 1;
    int param2 = 20;
    calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
    printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
    return 0;
}

非常感谢 Kaveh Vahedipour。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-25
    • 2022-01-19
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多