Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 推力应用的性能调整_C++_Performance_Thrust_Benchmarking - Fatal编程技术网

C++ 推力应用的性能调整

C++ 推力应用的性能调整,c++,performance,thrust,benchmarking,C++,Performance,Thrust,Benchmarking,我正在我的macbook pro w/9600M GT gpu上运行一个小的C++/推力程序(如下),我对了解函数h的时间花费在哪里很感兴趣,因为目标是尽可能快地运行此代码以获得更大的NEPS值 为此,我在函数中加入了clock()调用 打印的时间表明,几乎所有的时间都花在减少推力上。 事实上,报告的推力::reduce的时间是推力::transform的数百倍,后者调用每个元素的三个余弦调用。为什么? 当然,我对测量的时间表示怀疑。 我给推力::减少插入了第二个调用,只是想看看报告的时间是否相

我正在我的macbook pro w/9600M GT gpu上运行一个小的C++/推力程序(如下),我对了解函数h的时间花费在哪里很感兴趣,因为目标是尽可能快地运行此代码以获得更大的NEPS值

为此,我在函数中加入了clock()调用

打印的时间表明,几乎所有的时间都花在减少推力上。 事实上,报告的推力::reduce的时间是推力::transform的数百倍,后者调用每个元素的三个余弦调用。为什么?

当然,我对测量的时间表示怀疑。 我给推力::减少插入了第二个调用,只是想看看报告的时间是否相似:不是。第二次呼叫报告的时间具有更高的方差,并且更小。 更多的困惑:为什么

我还尝试过使用推力::transform_reduce(注释掉)代替两个期望运行更快的内核调用——相反,它慢了4%。为什么?

感谢您的建议

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <iostream>

#include <stdio.h>
#include <stdint.h>


 float NEPS = 6.0;
 __device__ float EPS;
 __device__ float SQEPS;

 __device__ float CNV_win;
 __device__ float CNV_dt;
 int CNV_n;
 float EU_dt;

__host__ __device__ float f(float x,float t){
    return x*cos(t)+x*cos(t/SQEPS)+cos(t/EPS);
}

struct h_functor
{
  const float x, t;
  h_functor(float _x, float _t) : x(_x),t(_t) {}
  __host__ __device__
  float operator()(const float & t_f) const {
    return f(x,   t-CNV_win+CNV_dt*(t_f+1)   )*CNV_dt;
  } 
};


clock_t my_clock() __attribute__ ((noinline));
clock_t my_clock() {
  return clock();
}
float h(float x,float t){
    float sum;

    sum = CNV_dt*(f(x,t-CNV_win/2)+f(x,t+CNV_win/2))/2;
    clock_t start = my_clock(), diff1, diff2, diff3, diff4, diff5;
    thrust::device_vector<float> t_f(CNV_n-2);
    diff1 = my_clock() - start;
    /* initialize t_f to 0.. CNV_n-3 */
    start = my_clock();
    thrust::sequence(t_f.begin(), t_f.end());
    diff2 = my_clock() - start;

    start = my_clock();
    thrust::transform(t_f.begin(), t_f.end(), t_f.begin(), h_functor(x,t));
    diff3 = my_clock() - start;
    start = my_clock();
    sum += thrust::reduce(t_f.begin(), t_f.end());
    diff4 = my_clock() - start;
    start = my_clock();
    sum += thrust::reduce(t_f.begin(), t_f.end());
    diff5 = my_clock() - start;
#define usec(d) (d)
    fprintf(stderr, "Time taken %ld %ld %ld %ld %ld usecs\n", usec(diff1), usec(diff2), usec(diff3), usec(diff4), usec(diff5));
        /* a bit slower, surprisingly:
       sum += thrust::transform_reduce(t_f.begin(), t_f.end(), h_functor(x,t), 0, thrust::plus<float>());
       */

    return sum;
}
main(int argc, char ** argv) {
  if (argc >= 1) NEPS = strtod(argv[1], 0);
  fprintf(stderr, "NEPS = %g\n", NEPS);

  EPS= powf(10.0,-NEPS);
  SQEPS= powf(10.0,-NEPS/2.0);
  CNV_win= powf(EPS,1.0/4.0);
  CNV_dt = EPS;
  CNV_n = powf(EPS,-3.0/4.0);
  EU_dt = powf(EPS,3.0/4.0);

  cudaMemcpyToSymbol(CNV_win, &CNV_win, sizeof(float));
  cudaMemcpyToSymbol(CNV_dt, &CNV_dt, sizeof(float));
  cudaMemcpyToSymbol(SQEPS, &SQEPS, sizeof(float));
  cudaMemcpyToSymbol(EPS, &EPS, sizeof(float));

  float x=1.0;
  float t = 0.0;
  int n = floor(1.0/EU_dt);
  fprintf(stderr, "CNV_n = %d\n", CNV_n);
  while (n--) {
    float sum = h(x,t);
    x=x+EU_dt*sum;
    t=t+EU_dt;
  }
  printf("%f\n",x);
}
#包括
#包括
#包括
#包括
#包括
#包括
浮子棉结=6.0;
__装置浮式EPS;
__设备浮球;
__设备浮动CNV\u win;
__装置浮点数;
国际网络;
浮动EU_dt;
__主机设备浮点数f(浮点数x,浮点数t){
返回x*cos(t)+x*cos(t/SQEPS)+cos(t/EPS);
}
结构h_函子
{
常数浮点x,t;
h_函子(float x,float t):x(x),t(t){
__主机设备__
浮点运算符()(常量浮点和t_f)常量{
返回f(x,t-CNV_-win+CNV_-dt*(t_-f+1))*CNV_-dt;
} 
};
clock_t my_clock()___属性__((noinline));
时钟不是我的时钟{
返回时钟();
}
浮子h(浮子x、浮子t){
浮点数;
sum=CNV_dt*(f(x,t-CNV_-win/2)+f(x,t+CNV_-win/2))/2;
时钟开始=我的时钟(),diff1,diff2,diff3,diff4,diff5;
推力:装置矢量t_f(CNV_n-2);
diff1=我的时钟()-开始;
/*将t\u f初始化为0..CNV\u n-3*/
开始=我的时钟();
推力::序列(t_f.begin(),t_f.end());
diff2=我的时钟()-开始;
开始=我的时钟();
变换(t_f.begin(),t_f.end(),t_f.begin(),h_函子(x,t));
diff3=我的时钟()-开始;
开始=我的时钟();
sum+=推力::减少(t_f.begin(),t_f.end());
diff4=我的时钟()-开始;
开始=我的时钟();
sum+=推力::减少(t_f.begin(),t_f.end());
diff5=我的时钟()-开始;
#定义usec(d)(d)
fprintf(标准,“所用时间%ld%ld%ld%ld%ld%ld usecs\n”、usec(diff1)、usec(diff2)、usec(diff3)、usec(diff4)、usec(diff5));
/*有点慢,令人惊讶:
sum+=推力::变换减少(t_f.begin(),t_f.end(),h_函子(x,t),0,推力::plus());
*/
回报金额;
}
主(内部argc,字符**argv){
如果(argc>=1)NEPS=strtod(argv[1],0);
fprintf(标准,“NEPS=%g\n”,NEPS);
EPS=功率因数(10.0,-NEPS);
SQEP=功率因数(10.0,-NEPS/2.0);
CNV_win=功率(EPS,1.0/4.0);
CNV_dt=每股收益;
CNV_n=功率(EPS,-3.0/4.0);
EU_dt=功率(EPS,3.0/4.0);
cudaMemcpyToSymbol(CNV_-win和CNV_-win,sizeof(float));
cudaMemcpyToSymbol(CNV_dt和CNV_dt,sizeof(float));
cudaMemcpyToSymbol(SQEPS和SQEPS,sizeof(float));
cudaMemcpyToSymbol(每股收益和每股收益,浮点数);
浮动x=1.0;
浮动t=0.0;
int n=地板(1.0/EU_dt);
fprintf(标准,“CNV_n=%d\n”,CNV_n);
而(n--){
浮点数和=h(x,t);
x=x+EU_dt*sum;
t=t+EU_dt;
}
printf(“%f\n”,x);
}

如果您想优化算法的性能,可以选择使用arrayfire。我冒昧地重写了arrayfire的代码,您可以将其与推力版本进行比较,并选择运行速度更快的版本:

float h(float x,float t){

 float sum = CNV_dt * (f(x, t - CNV_win/2) + f(x, t + CNV_win/2)) / 2;
 // initialize t_f with a sequence 0..CNV_n-3
 af::array t_f(af::seq(0, CNV_n-3));

 // transform vector on the GPU
 t_f =  t - CNV_win + CNV_dt*(t_f+1); 
 t_f = (x*cos(t_f) + x*cos(t_f/SQEPS) + cos(t_f/EPS)) * CNV_dt;

 sum += af::sum<float>(t_f); // sum up all elements of the vector
 return sum;
}
浮点h(浮点x,浮点t){
浮动总和=CNV_dt*(f(x,t-CNV_-win/2)+f(x,t+CNV_-win/2))/2;
//用序列0..CNV_n-3初始化t_f
af::数组t_f(af::seq(0,CNV_n-3));
//GPU上的变换向量
t_f=t-CNV_win+CNV_dt*(t_f+1);
t_f=(x*cos(t_f)+x*cos(t_f/SQEPS)+cos(t_f/EPS))*CNV_dt;
sum+=af::sum(t_f);//对向量的所有元素求和
回报金额;
}

另外,请注意,不需要将变量显式复制到GPU(即不需要cudaMemcpyToSymbol调用)

最好不要在多核环境中使用clock()函数。给出错误的答案是愚蠢的

最好使用挂钟计时。在Windows上,我们还有一些高分辨率计时器

在使用CUDA时,最好使用CUDA自己提供的计时器。角质计时器


阅读答案。它可能对您的代码有用。@abinhole:谢谢!在时钟调用之前添加cudaDeviceSynchronize()调用会产生更合理的结果。