0

私は Rootbeer の使い方を学んでいますが、そのサンプル アプリを実行したときに行き詰まり、誰も私の質問に答えることができませんでした: Rootbeer ランタイム エラー、修正方法は?

そこで、Rootbeer のソース コードをダウンロードし、コードを調べてみました。問題は [ CUDAContext.java:119 ] です。

          public void setKernel(Kernel kernelTemplate) {
            this.kernelTemplate = kernelTemplate;
 [ 119 ]    this.compiledKernel = (CompiledKernel) kernelTemplate;
          }

Kernel と CompiledKernel の定義は次のとおりです。

public interface Kernel
{
  public void gpuMethod();
}

public interface CompiledKernel
{
  public String getCodeUnix();

  public String getCodeWindows();

  public int getNullPointerNumber();

  public int getOutOfMemoryNumber();

  public String getCubin32();

  public int getCubin32Size();

  public boolean getCubin32Error();

  public String getCubin64();

  public int getCubin64Size();

  public boolean getCubin64Error();

  public Serializer getSerializer(Memory memory,Memory memory1);

  public boolean isUsingGarbageCollector();
}

119行目でキャストは適切に行われていますか?そうである場合、なぜ次のようなエラーが表示されたのですか。

java.lang.ClassCastException: ArrayMult cannot be cast to org.trifort.rootbeer.runtime.CompiledKernel
    at org.trifort.rootbeer.runtime.CUDAContext.setKernel(CUDAContext.java:119)

正しく行われていない場合、キャストする正しい方法は何ですか?

編集:これがサンプルコードです

import java.util.List;
import java.util.ArrayList;
import org.trifort.rootbeer.runtime.Kernel;
import org.trifort.rootbeer.runtime.Rootbeer;

public class ArrayMultApp
{  
  public ArrayMultApp()
  {
    int[] array=new int[10];
    for (int i=0;i<array.length;++i) array[i]=i;
    for (int i=0;i<array.length;++i) Out("start array["+i+"]: "+array[i]);
    multArray(array);
    for (int i=0;i<array.length;++i) Out("final array["+i+"]: "+array[i]);
  }

  public void multArray(int[] array)
  {
    try
    {
      List<Kernel> jobs=new ArrayList();
      for (int i=0;i<array.length;++i) jobs.add(new ArrayMult(array,i));
      Rootbeer rootbeer=new Rootbeer();
      rootbeer.run(jobs);
    }
    catch (Exception e) { e.printStackTrace(); }
  }

  public static void main(String[] args) { ArrayMultApp app=new ArrayMultApp(); }

  private static void out(String message) { System.out.print(message); }

  private static void Out(String message) { System.out.println(message); }
}

class ArrayMult implements Kernel
{
  private int[] m_source;
  private int m_index;

  public ArrayMult(int[] source,int index)
  {
    m_source=source;
    m_index=index;
  }

  public void gpuMethod() { m_source[m_index]*=11; }
}
4

3 に答える 3

1

私は G カードを持っていないため、コードをテストできません。ソースコードに目を通してみました。著者は org.trifort.rootbeer.compiler.Transform2.java でこのトリックを行いました

public void run(String cls){    
  OpenCLScene scene = new OpenCLScene();
  OpenCLScene.setInstance(scene);
  scene.init();

  SootClass soot_class1 = Scene.v().getSootClass(cls);
  SootMethod method = soot_class1.getMethod("void gpuMethod()");

  String uuid = getUuid();
  GenerateForKernel generator = new GenerateForKernel(method, uuid);
  try {
    generator.makeClass();
  } catch(Exception ex){
    ex.printStackTrace();
    OpenCLScene.releaseV();
    return;
  }

  //add an interface to the class
  SootClass soot_class = method.getDeclaringClass();
  SootClass iface_class = Scene.v().getSootClass("org.trifort.rootbeer.runtime.CompiledKernel");
  soot_class.addInterface(iface_class);

  System.out.println("added interface CompiledKernel");

  OpenCLScene.releaseV();
}

彼のデモ コード「examples\sort\src\org\trifort\rootbeer\sort\GPUSort.java」も調べました。作成者は Contex を初期化しましたが、これはあなたのコードとは異なります。最初に彼のコードを試すことをお勧めします。あなたのコードでは Transform2.run 関数を呼び出していないはずです。

public void sort(){
  //should have 192 threads per SM
  int size = 2048;
  int sizeBy2 = size / 2;
  //int numMultiProcessors = 14;
  //int blocksPerMultiProcessor = 512;
  int numMultiProcessors = 2;
  int blocksPerMultiProcessor = 256;
  int outerCount = numMultiProcessors*blocksPerMultiProcessor;
  int[][] array = new int[outerCount][];
  for(int i = 0; i < outerCount; ++i){
    array[i] = newArray(size);
  }

  Rootbeer rootbeer = new Rootbeer();
  List<GpuDevice> devices = rootbeer.getDevices();
  GpuDevice device0 = devices.get(0);
  Context context0 = device0.createContext(4212880);
  context0.setCacheConfig(CacheConfig.PREFER_SHARED);
  context0.setThreadConfig(sizeBy2, outerCount, outerCount * sizeBy2);
  context0.setKernel(new GPUSortKernel(array));
  context0.buildState();
  ......
}
于 2014-12-14T17:38:02.560 に答える
1

いいえ、ちがいます。2 つの異なるインターフェイスがあります。

     public void setKernel(Kernel kernelTemplate) {
        this.kernelTemplate = kernelTemplate;
 [ 119 ]    this.compiledKernel = (CompiledKernel) kernelTemplate;
      }

119 では、Kernel を CompiledKernel にキャストしようとしていますが、それぞれに独自の階層があります。の場合CompiledKernel extends Kernel、これは機能します。

于 2014-12-14T16:32:10.943 に答える
0

実際のオブジェクトがそのインターフェイスを実装している場合にのみ、インターフェイスにキャストできます。CUDA についてはよくわかりませんが、カーネルを受け取り、CompiledKernel を返すメソッドがどこかにあるかもしれません。ただキャストするだけではそうはいきません。

一方、「ArrayMult」クラスの作成者であれば、Kernel と CompiledKernel の両方を実装することでこの問題を解決できます。

于 2014-12-14T17:49:46.853 に答える