DirectX - ページ 3

 
Rorschach:

ありがとうございました。

計算はダブルで行っていますか?それから、特に印象的なのはその結果です。

良い点です。確かに、あるところではdoubleではなく floatになって いました。

D = fast_length(p);

ダブルにするためには、次のように修正する必要があります。

D = length(p);

また、引数 *buf にuint ではなくuchar4 を適用することで、最後の行(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倍高い。

ありがとうございます。コードは動作し、パフォーマンスの低下もありません。ただ、最後の行でアルファチャンネルを最後に移動させました。

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を整数にする必要があります。その価値観の広がりがどの程度なのかを見て、あまり罪がないように掛け合わせることができるかもしれません。そして、ループを3次元に移行することが可能で、理論的にはNが高い値でも性能が向上する。

HD7950でフルHDモニターでN=128で80~90fps出るんだけど。

 
Serhii Shevchuk:

この実装では、性能はセンターの数(N)に大きく依存する。カーネル 内のループをなくせばいいのですが、そうするとS1とS2が整数でないといけなくなります。その価値観の広がりがどの程度なのかを見て、あまり罪がないように掛け合わせることができるかもしれません。そして、ループを3次元に転送することが可能で、理論的にはNが高い値でも性能を上げることができます。

N=128でフルHDモニタのHD7950で80〜90fps出るんだけど。

私の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

論理的には、floatに切り替えることで、amdで4倍、nvidiaで32倍のfpsを上げることができます。

 

OCL版のコピーを作成。この結果にはショックを受けています。1600センターでは、ビデオアドを85%以上ロードすることができませんでした。

事前に計算されたhで最適化しても効果はなく、そのまま放置。すべての計算はfloatで行われます。どうせすべての関数はfloatを返すので、doubleを使う意味はないと思います。

ファイル:
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)ifを解消する際に、特に違いを感じなかった。

3)速度が遅くなる。

それより

だそうです

4) CPUのオフロードができない、つまりスキャルパーのスタックなどが 忘れられる。

MT5では、スキャルパースタックはOCLなしで1つのスレッドで簡単に実行でき、CPUに負荷をかけることはありません。もちろん、不要というわけではありません。ご参考までに。

マリオンを作成する際にCCanvasクラスを 使用した場合、作業量はマリオンの面積に比例することになります。つまり、Mullのウィンドウが大きくなればなるほど、個々の変更箇所ではなく、キャンバス全体が再描画されるため、負荷が重くなるのです。しかし、ビーカーセルを独立した要素にすることで、他のキャンバス領域とは独立して更新することができ、再描画時間やそれによるプロセッサの負荷を数分の一に低減することができました。

 
Реter Konow:

MT5では、スキャルパースタックは、OCLを使用せず、プロセッサに負荷をかけずに、1つのスレッドで簡単に動作させることができます。もちろん、それが必要ないわけではありません。ご参考までに。

マリオンを構築する際にCCanvasクラスを使用する場合、作業量はマリオンのサイズに比例することになります。つまり、個々の変更箇所ではなく、キャンバス全体を再描画するため、マルのウィンドウが大きくなるほど負荷が重くなる。しかし、ビーカーセルを独立した要素にすることで、他のキャンバス領域とは独立して更新することができ、再描画時間やそれによるプロセッサの負荷を数分の一に低減することができました。

4点目の問題点Remnant3Dの例では、CPUにほとんど負荷がかかっていません。

 
Rorschach:

ポイント4が問題です。Remnant3Dの例では、CPUにほとんど負荷をかけません。

これはテスト済みです。MT5では、キャンバスの動きが正常な場合、値が変化したセルを個別に再描画すれば、CPUはほとんど負荷がかかりません。

逆に、入力された値がすべてキャンバス領域全体に再描画されると、プロセッサに大きな負荷がかかることになります。

違いは、画素配列の再初期化される値の数です。個々の領域を選択的にアップデートする必要があり、負荷の問題は発生しません。

 
Реter Konow:

これはテスト済みです。MT5では、キャンバスの動きが正常な場合、値が変化したセルを個別に再描画すれば、CPUはほとんど負荷がかかりません。

逆に、入力された値がすべてキャンバス領域全体に再描画されると、プロセッサに大きな負荷がかかることになります。

違いは、画素配列の再初期化される値の数です。個々の領域を選択的にアップデートする必要があり、負荷の問題は発生しません。

それがRemnant3Dでは、フルスクリーンのキャンバスで、CPUに負荷をかけないのです。