package dr.evomodel.newtreelikelihood;
import dr.app.beagle.evomodel.treelikelihood.AbstractTreeLikelihood;
import java.util.logging.Logger;
/**
* @author Marc Suchard
* @author Andrew Rambaut
* @author Dat Hunyh
*
*/
public class GPULikelihoodCore extends NativeLikelihoodCore {
/**
* Constructor
*
* @param treeLikelihood reference back to ATL, should be able to remove at some point
* @param gpuInfo number of states
*/
public GPULikelihoodCore(int deviceNumber, int stateCount, AbstractTreeLikelihood treeLikelihood, GPUInfo gpuInfo) {
StringBuffer sb = new StringBuffer();
sb.append("Constructing GPU likelihood core:\n");
sb.append("\tGPU Name: "+gpuInfo.getName(deviceNumber)+"\n");
// sb.append("\tOther info here: "+gpuInfo.memorySize[deviceNumber]+"\n");
sb.append("If you publish results using this core, please reference Suchard and Rambaut (in preparation)\n");
Logger.getLogger("dr.evomodel.treelikelihood").info(sb.toString());
this.treeLikelihood = treeLikelihood;
this.stateCount = stateCount;
}
private int stateCount;
private AbstractTreeLikelihood treeLikelihood; // TODO Not needed if everything runs in one thread or I get GPU contexts working
/** GPU-specific loading **/
protected static String GPU_LIBRARY_NAME = "GPULikelihoodCore";
protected static boolean isCompatible(GPUInfo gpuInfo, int[] configuration) {
return true;
}
/** GPU-specific native interface **/
private static native GPUInfo getGPUInfo();
public boolean canHandleTipPartials() {
return true;
}
public boolean canHandleTipStates() {
return false;
}
/** Native interface overriding NativeLikelihoodCore **/
public void initialize(int nodeCount, int stateTipCount, int patternCount, int matrixCount) {
// System.err.println("stateCOunt = "+stateCount+" in java");
initialize(nodeCount, stateTipCount, patternCount, matrixCount, stateCount);
}
public native void initialize(int nodeCount, int stateTipCount, int patternCount, int matrixCount, int stateCount);
private native void freeNativeMemory();
public native void setTipPartials(int tipIndex, double[] partials);
public native void setTipStates(int tipIndex, int[] states);
protected native void updateRootFrequencies(double[] frequencies);
protected native void updateEigenDecomposition(double[][] eigenVectors, double[][] inverseEigenValues, double[] eigenValues);
protected native void updateCategoryRates(double[] rates);
protected native void updateCategoryProportions(double[] proportions);
public native void updateMatrices(int[] branchUpdateIndices, double[] branchLengths, int branchUpdateCount);
public native void updatePartials(int[] operations, int[] dependencies, int operationCount);
public native void calculateLogLikelihoods(int rootNodeIndex, double[] outLogLikelihoods);
public native void storeState();
public native void restoreState();
private static GPUInfo gpuInfo = null;
public static class LikelihoodCoreLoader implements LikelihoodCoreFactory.LikelihoodCoreLoader {
public String getLibraryName() { return GPU_LIBRARY_NAME; }
public LikelihoodCore createLikelihoodCore(int[] configuration, AbstractTreeLikelihood treeLikelihood) {
int stateCount = configuration[0];
int paddedStateCount = stateCount;
int deviceNumber = 0;
if ( stateCount == 4 )
paddedStateCount = 4;
else if ( stateCount <= 16 )
paddedStateCount = 16;
else if (stateCount <= 32 )
paddedStateCount = 32;
else if (stateCount <= 64 )
paddedStateCount = 64;
try {
System.loadLibrary(getLibraryName()+"-"+paddedStateCount);
if (gpuInfo == null) {
gpuInfo = GPULikelihoodCore.getGPUInfo();
if (gpuInfo == null) // No GPU is present
return null;
Logger.getLogger("dr.evomodel.treelikelihood").info(gpuInfo.toString());
}
if (!GPULikelihoodCore.isCompatible(gpuInfo, configuration)) // GPU is not compatible
return null;
} catch (UnsatisfiedLinkError e) { // No library present
return null;
}
return new GPULikelihoodCore(deviceNumber,stateCount, treeLikelihood, gpuInfo);
}
}
}