视觉特效 - 页 3

 
Rorschach:

非常感谢您!

你的计算结果是双倍的吗?那么结果就会特别令人印象深刻。

说得好。事实上,在一个地方,它是浮动 的,而不是双倍 的。

D = fast_length(p);

为了使其成为双倍,我们需要将其修正为

D = length(p);

另外,你可以通过对*buf参数应用ugar4 而不是uint 来摆脱最后一行(类似于XRGB宏)。这样试试吧。

__kernel void Func(int N, __global double *XP, __global double *YP, __global uchar *h, __global uchar4 *buf)
{
   size_t X = get_global_id(0);
   size_t Width = get_global_size(0);
   size_t Y = get_global_id(1);
   
   float2 p;
   double D=0,S1=0,S2=0;
   
   for(int w=0;w<N;w++){ 
      p.x = XP[w]-X;
      p.y = YP[w]-Y;
      D = length(p);
      S2+=D;
      if(w<N/2)
         S1+=D;
   }   
   //
   double d=S1/S2;
   buf[Y*Width+X] = (uchar4)(0xFF,h[(int)(d*11520)],h[(int)(d*17920)],h[(int)(d*6400)]);
}
 
Serhii Shevchuk:

这真的令人印象深刻!Fps比着色器上高1.5倍。

谢谢,代码可以使用,没有性能下降,只是在最后一行把alpha通道移到了最后。

buf[Y*Width+X] = (uchar4)(h[(int)(d*11520)],h[(int)(d*17920)],h[(int)(d*6400)],0xFF);
 
Rorschach:

这真的令人印象深刻!Fps比着色器上高1.5倍。

谢谢,代码可以使用,性能没有下降,只是在最后一行,阿尔法通道被移到了最后。

在这个实现中,性能高度依赖于中心的数量(N)。理想情况下,我们应该摆脱内核 中的循环,但这样我们就必须使S1和S2成为整数。我们将不得不看看他们的价值传播有多大,也许我们可以乘以一些东西,而不会有太多的罪恶。然后有可能将循环转移到第三维,理论上这将在N的高值下获得性能增益。

我的HD7950在全高清显示器上得到80-90帧,N=128。

 
Serhii Shevchuk:

在这个实现中,性能高度依赖于中心的数量(N)。摆脱内核 中的循环会很好,但那样的话S1和S2就必须是整数了。我们将不得不看看他们的价值传播有多大,也许我们可以乘以一些东西,而不会有太多的罪恶。然后有可能将一个循环转移到第三维,理论上会在N的高值上获得性能增益。

我的HD7950在N=128的全高清显示器上得到80-90帧。

我的750ti有11fps。我找到了这些卡的规格。

GPU
FP32 GFLOPS
FP64 GFLOPS 比率
Radeon HD 7950 2867 717 fp64 = 1/4 fp32
GeForce GTX 750 Ti 1388 43 fp64 = 1/32 fp32

从逻辑上讲,在amd上切换到float可以提高4倍的帧数,在nvidia上可以提高32倍。

 

制作了一份OCL版本的副本。我对这个结果感到震惊。在1600中心无法加载超过85%的vidia。

用预先计算好的h进行优化没有效果,但留下了它。所有的计算都是浮动的,我看不出使用双倍的意义,因为反正所有的函数都返回浮动的。

附加的文件:
pixel.zip  1 kb
 

一些结论。

1)预先计算h没有影响。

2)在摆脱如果时,我没有注意到任何区别。

S1+=D*(i<0.5 f*N);
//if(i<N*0.5 f) S1+=D;

3)它的速度较慢。

for(int i=0;i<N;i++)
  {XP[i]= (1.f-sin(j/iArr[2*i  ].w))*wh.x*0.5 f;
   YP[i]= (1.f-cos(j/iArr[2*i+1].w))*wh.y*0.5 f;
  }
float S1=0.f,S2=0.f;
for(int i=0;i<N;i++)
  {float2 p;
   p.x=XP[i]-Pos.x;
   p.y=YP[i]-Pos.y;
   ...
  }

比它

float S1=0.f,S2=0.f;
for(int i=0;i<N;i++)
  {float2 p;
   p.x=(1.f-sin(j/iArr[2*i  ].w))*wh.x*0.5 f-Pos.x;
   p.y=(1.f-cos(j/iArr[2*i+1].w))*wh.y*0.5 f-Pos.y;
   ...
  }

看来...

4)不能卸载CPU,即黄牛的堆 栈等可以忘记。

 
Rorschach:

一些结论。

1)预先计算h没有影响。

2)在摆脱如果时,我没有注意到任何区别。

3)它的速度较慢。

比它

看来...

4)不能卸载CPU,即黄牛的堆栈等可以忘记。

在MT5中,黄牛堆栈可以很容易地在一个线程中运行,不需要OCL,也不会使CPU过载。当然,这并不意味着不需要它。仅供参考。

如果你在建立木板时使用CCanvas类,那么工作量将与木板的面积成正比。也就是说,mull中的窗口越大,负载就越重,因为整个画布都会被重绘,而不是单个的、被改变的部分。然而,将烧杯单元变成独立的元素,它们可以独立于画布区域的其他部分进行更新,将重绘时间和由此引起的处理器负载减少了数倍。

 
Реter Konow:

在MT5上,黄牛堆栈可以很容易地在一个线程中工作,不需要OCL,也不会使处理器过载。当然,这并不意味着不需要它。仅供参考。

如果你在构建木板时使用CCanvas类,那么工作量将与木板的大小成正比。也就是说,Mull中的窗口越大,负载就越重,因为整个画布都在重绘,而不是个别的、变化的部分。然而,将烧杯单元变成独立的元素,它们可以独立于画布区域的其他部分进行更新,将重绘时间和由此造成的处理器负载减少了数倍。

第4点问题。在Remnant3D的例子中,CPU几乎没有负荷。

 
Rorschach:

第4点是有问题的。Remnant3D的例子几乎没有加载CPU。

这已经过测试。MT5的CPU,在画布正常动态的情况下,如果你重新绘制数值发生变化的个别单元格,几乎没有负荷。

相反,如果每个传入的值都要在整个画布区域上重绘,那么处理器的压力就会很大。

区别在于像素阵列中重新初始化的值的数量。你需要有选择地更新个别区域,你就不会有负载问题。

 
Реter Konow:

这已经过测试。MT5的CPU,在画布正常动态的情况下,如果你重新绘制数值发生变化的个别单元格,则几乎没有负荷。

相反,如果每个传入的值都要在整个画布区域上重绘,那么处理器的压力就会很大。

区别在于像素阵列中重新初始化的值的数量。你需要有选择地更新个别区域,你就不会有负载问题。

这就是Remnant3D的特点:它是一个全屏画布,不会加载CPU。