0

特に、ゲームに取り組んでおり、FPS が期待どおりに増加するため、CPU よりも GPU を使用することを好むことにしました。問題は、どこから始めればよいかわからないということです。JOCL または JCUDA を簡単に実装できますが、その後、CPU を使用して GPU に置き換える場所がわかりません。助けていただければ幸いです:)

4

1 に答える 1

1

あなたはどのような計算をしていますか?それらがN体重力実験などの計算集約型の場合、変数をgpuにコピーして計算し、結果をメインメモリにコピーするだけです。

オブジェクトに大きなデータがあるが、流体力学や衝突検出などの小さな計算がある場合は、グラフィックス API と計算 API の間に相互運用性を追加する必要があります。次に、データをコピーせずに計算のみを実行できます (速度向上は、GPU RAM 帯域幅を PCI-E 帯域幅で割ったようなものです。HD7870 の場合、計算能力がまだ飽和していない場合は 25 倍のようになります)

Java で gl/cl 相互運用性を使用して jocl と lwjgl を使用しましたが、非常にうまく機能していました。

一部のニューラル ネットワークは CPU(Encog) でトレーニングされますが、マップを生成するために GPU(jocl) によって使用され、LWJGL によって描画されます:(ニューロンの重みは、ランダム化効果を高めるために少し変更されます)

ここに画像の説明を入力

ここに画像の説明を入力

非常に重要な部分は次のとおりです。

  • GL コンテキストを開始します。
  • GL コンテキストのハンドル変数を使用して相互運用可能な CL コンテキストを開始する
  • GL バッファを作成する
  • 相互運用可能な cl コンテキストを使用して CL バッファーを作成します。
  • opencl が完了し、gl を開始する準備ができたら、clFinish() を呼び出すことを忘れないでください
  • opengl が完了し、cl を開始する準備ができたら、glFinish() を呼び出すことを忘れないでください
  • opencl カーネル ビルダー/テーブル クラスとバッファー スケジューラー クラスを使用すると、gl と cl の間に多数の異なるカーネルがあり、それらを順番に実行する必要がある場合に役立ちます。

例:

 // clh is a fictional class that binds oepncl to opengl through interoperability
 // registering needed kernels to this object
 clh.addKernel(
               kernelFactory.fluidDiffuse(1024,1024),  // enumaration is fluid1
               kernelFactory.fluidAdvect(1024,1024),   // enumeration is fluid2
               kernelFactory.rigidBodySphereSphereInteracitons(2048,32,32), 
               kernelFactory.fluidRigidBodyInteractions(false), // fluidRigid
               kernelFactory.rayTracingShadowForFluid(true),
               kernelFactory.rayTracingBulletTargetting(true),
               kernelFactory.gravity(G),
               kernelFactory.gravitySphereSphere(), // enumeration is fall
               kernelFactory.NNBotTargetting(3,10,10,2,numBots) // Encog
               );

 clh.addBuffers(
         // enumeration is buf1 and is used as fluid1, fluid2 kernels' arguments
               bufferFactory.fluidSurfaceVerticesPosition(1024,1024, fluid1, fluid2),
        // enumeration is buf2, used by fluid1 and fluid2
               bufferFactory.fluidSurfaceColors(1024,1024,fluid1, fluid2),
        // enumeration is buf3, used by network
               bufferFactory.NNBotTargetting(numBots*25, Encog)
               )

 Running kernels:

 // shortcut of a sequence of kernels
 int [] fluidCalculations = new int[]{fluid1,fluid2,fluidRigid, fluid1} 

 clh.run(fluidCalculations); // runs the registered kernels
 // diffuses, advects, sphere-fluid interaction, diffuse again

 //When any update of GPU-buffer from main-memory is needed:

 clh.sendData(cpuBuffer, buf1); // updates fluid surface position from main-memory.

CPU コードを opencl コードに変更することは、APARAPI によって自動的に行うことができますが、相互運用性があるかどうかはわかりません。

自分で行う必要がある場合は、次のように簡単です。

 From Java:

 for(int i=0;i<numParticles;i++)
 {
     for(int j=0;j<numParticles;j++)
       {

           particle.get(i).calculateAndAddForce(particle.get(j));
       }
 }


 To a Jocl kernel string(actually very similar to calculateAndAddForce's inside):

   "__kernel void nBodyGravity(__global float * positions,__global float *forces)" +
                "{" +
                "    int indis=get_global_id(0);" +
                "    int totalN=" + n + "; "+            
                "    float x0=positions[0+3*(indis)];"+
                "    float y0=positions[1+3*(indis)];"+
                "    float z0=positions[2+3*(indis)];"+
                "    float fx=0.0f;" +
                "    float fy=0.0f;" +
                "    float fz=0.0f;" +
                "    for(int i=0;i<totalN;i++)" +
                "    { "+
                "       float x1=positions[0+3*(i)];" +
                "       float y1=positions[1+3*(i)];" +
                "       float z1=positions[2+3*(i)];" +

                "       float dx = x0-x1;" +
                "       float dy = y0-y1;" +
                "       float dz = z0-z1;" +
                "       float r=sqrt(dx*dx+dy*dy+dz*dz+0.01f);" +
                "       float tr=0.1f/r;" +
                "       float tr2=tr*tr*tr;" +
                "       fx+=tr2*dx*0.0001f;" +
                "       fy+=tr2*dy*0.0001f;" +
                "       fz+=tr2*dz*0.0001f;" +

                "    } "+


                "    forces[0+3*(indis)]+=fx; " +
                "    forces[1+3*(indis)]+=fy; " +
                "    forces[2+3*(indis)]+=fz; " +

               "}"
于 2013-09-18T13:28:42.683 に答える