蒙特卡洛积分优化

时间:2019-11-01 13:34:47

标签: c performance montecarlo

我正在使用gsl库中实现的montecarlo方法。我需要计算此整数的多次重复,从而更改被积分中的参数。所以我需要使我的子程序快速。似乎最耗时的部分是在随机点上对被积物的评估。在特定情况下,如何使评估更快? 这是一个最小的示例:

#include <gsl/gsl_rng.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_monte.h>
#include <gsl/gsl_monte_plain.h>
#include <gsl/gsl_monte_vegas.h>

double q=0.0;
double mu=0.001;
double eta=0.1;
double kF=1.0;
double Kcut=10;
long int Nmax=10000000;
int Nwu=1000000;
double w=1;


struct my_f_params { double y;};

double 
g (double *k, size_t dim, void *p)
{
  double A;
  struct my_f_params * fp = (struct my_f_params *)p;

  double PQ=q*q+k[1]*k[1]-2*q*k[1]*cos(k[3])+mu;
  double QK=k[0]*k[0]+k[1]*k[1]-2*k[0]*k[1]* (cos(k[2])*cos(k[3])+cos(k[4])*sin(k[2])*sin(k[3]))+mu;
  double KPQ=q*q+k[0]*k[0]+k[1]*k[1]+2*k[0]*cos(k[2])*(q-k[1]*cos(k[3]))+2*k[1]*       (q*cos(k[3])+k[0]*cos(k[4])*sin(k[2])*sin(k[3]));
  double denFreq=fp->y-0.5*(k[0]*k[0]+k[1]*k[1]+KPQ);
  double vol=k[0]*k[0]*k[1]*k[1]*sin(k[2])*sin(k[3]);
  if (sqrt(KPQ) < kF) {
    A = vol*denFreq*(1/QK-1/PQ)/(QK*(pow(denFreq,2)+eta*eta));
  }
  else {
    A = 0;
  }

  return A; 
}


int
main (void)
{
  double res, err;
  double xl[5] = {0, kF, 0, 0, 0};
  double xu[5] = {kF, Kcut, M_PI, M_PI, 2*M_PI};
  const gsl_rng_type *T;
  gsl_rng *r;
  gsl_monte_function G;
  size_t calls = Nmax;

  gsl_rng_env_setup ();
  struct my_f_params params;
  T = gsl_rng_default;
  r = gsl_rng_alloc (T);

  params.y=w;
  G.f=&g;
  G.dim=5;
  G.params=&params;

  {
    gsl_monte_vegas_state *s = gsl_monte_vegas_alloc (5);
    gsl_monte_vegas_integrate (&G, xl, xu, 5, Nwu, r, s,&res, &err);
    do
      {
        gsl_monte_vegas_integrate (&G, xl, xu, 5, calls/5, r, s,&res, &err);
      }
    while (fabs (gsl_monte_vegas_chisq (s) - 1.0) > 0.5);
    gsl_monte_vegas_free (s);
  }

  printf ("%.6f   %.6f   %.6f\n", w,res,err);
  gsl_rng_free (r);



  return 0;
}

1 个答案:

答案 0 :(得分:1)

扩展Bob__的注释,您可以使用sincos来计算相同参数(sincos)的k[2]k[3],并定义kF_sqr要在主体中初始化,并在g函数中使用它来避免进行sqrt调用。通过这些优化,在我的机器上进行的快速而肮脏的测试表明,与您的代码相比,速度提高了5%。