openmp 在 C 中为 Black Scholes 算法花费更长的时间

Posted

技术标签:

【中文标题】openmp 在 C 中为 Black Scholes 算法花费更长的时间【英文标题】:open mp taking longer for black_scholes algorithm in C 【发布时间】:2018-05-01 19:16:59 【问题描述】:

我在处理这个 black_scholes 代码片段时遇到了问题,我添加了一个简单的 #pragma omp parallel for 但它需要 50 倍以上的时间 我确定共享内存有问题,但我真的不知道是什么

black_scholes_iterate (void* the_args)

  black_scholes_args_t* args = (black_scholes_args_t*) the_args;

/* Unpack the IN/OUT struct */

 /* IN (read-only) parameters */
 const int S = args->S;
const int E = args->E;
const int M = args->M;
const double r = args->r;
const double sigma = args->sigma;
const double T = args->T;

/* OUT (write-only) parameters */
double* trials = args->trials;
double mean = 0.0;

/* Temporary variables */
gaus-s-rand_state_t gaus-s-rand_state;
void* prng_stream = NULL; 
int k;

/* Spawn a random number generator */
prng_stream = spawn_prng_stream (0);

/* Initialize the Gaussian random number module for this thread */
init_gaus-s-rand_state (&gaus-s-rand_state);

/* Do the Black-Scholes iterations */
printf("here2: %d \n",M);


#pragma omp  parallel for
for (k = 0; k < M; k++)
  
    const double gaussian_random_number = gaus-s-rand1 (&uniform_random_double,
                        prng_stream,
                        &gaus-s-rand_state);
    trials[k] = black_scholes_value (S, E, r, sigma, T, 
                   gaussian_random_number);

  /*
   * We scale each term of the sum in order to avoid overflow. 
   * This ensures that mean is never larger than the max
   * element of trials[0 .. M-1].
   */
  mean += trials[k] / (double) M;

经过进一步测试,我注意到 for 循环的 htis 部分需要很多时间: const double gaussian_random_number = gaus-s-rand1 (&uniform_random_double,prng_stream, &gaus-s-rand_state);

【问题讨论】:

变量mean 在循环的每次迭代中都会被修改。我并没有真正的 OpenMP 经验,但这似乎与并行化不符。 编辑: parallel 在您的代码中也缺少一个字母。这只是复制错误吗? 是的,实际上它只是一个复制错误,这就是我所认为的错误是平均部分,但 for 循环并没有使用该变量只是添加到它 添加到变量 is 使用它。异步添加到变量会导致竞争条件。如果您计算该 OpenMP 循环之外的平均值会发生什么?或者,如果您利用 C11 的 Atomic 类型和 mean 操作怎么办? 你能给我一个在循环外计算平均值的例子吗? 只需注释掉倒数第二行,这样您就不再计算循环中的平均值并查看它是否有所作为。事后计算它或通过在每个 OMP 线程本地计算它是微不足道的。但是先把它去掉,看看是不是卡点。 【参考方案1】:
double *a;
a = malloc(M * sizeof (double));

for (int k = 0; k < M; k++)


  const double gaussian_random_number = gaus-s-rand1 (&uniform_random_double,
                        prng_stream,
                        &gaus-s-rand_state);
  a[k]=gaussian_random_number;


#pragma omp  parallel for 
   for (int k = 0; k < M; k++)


  trials[k] = black_scholes_value (S, E, r, sigma, T, 
                   a[k]);




  mean += trials[k] / (double) M;

@Z Boson 的回答是解决方案,我的速度得到了显着提升,非常感谢您

【讨论】:

#pragma omp parallel for reduction(+: mean)

以上是关于openmp 在 C 中为 Black Scholes 算法花费更长的时间的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ OpenMP 中为每个线程定义一个优先级队列

如何在 CMake 的 try_compile 函数中为 OpenMP 设置链接器标志

OpenMP 并行代码运行速度较慢

OpenMp根据变量设置并行循环的线程数

我可以安全地将 OpenMP 与 C++11 一起使用吗?

混合 C++11 原子和 OpenMP