В Java как правильно привести интерфейс?
Я учусь использовать 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; }
}
3 ответа
Нет, это не так. У вас есть два разных интерфейса.
public void setKernel(Kernel kernelTemplate) {
this.kernelTemplate = kernelTemplate;
[ 119 ] this.compiledKernel = (CompiledKernel) kernelTemplate;
}
На 119 вы пытаетесь привести Kernel к CompiledKernel, каждый из которых имеет свою собственную иерархию. Если CompiledKernel extends Kernel
тогда это будет работать.
У меня нет карты 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();
......
}
Вы можете привести к интерфейсу, только если реальный объект реализует этот интерфейс. Я не знаю много о CUDA, но где-то может быть метод, который берет ядро и возвращает CompiledKernel. Просто кастинг не собирается делать это.
С другой стороны, если вы являетесь создателем класса "ArrayMult", то вы можете решить эту проблему, реализовав как Kernel, так и CompiledKernel.