diff --git a/CREDITS.txt b/CREDITS.txt index a681e5d9e5d2f8c7e2012ec394f1380d2d550f66..dff5142547a5e5e30d15cacb7b49bae6ba79c305 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -11,4 +11,5 @@ Ryan LaMothe provided patch for issue #3 (Support of char - mapped to unsigned s Ryan LaMothe provided patch for issue #22 (Integrate FindBugs into the Ant build scripts) Feb 18th 2012. Ryan LaMothe provided patch for issue #37 (Add Kernel and JNI build support for Applets and JNLP JWS) Feb 18th 2012. Oliver Coleman provided patch for issue #64 (Support explicit boolean put and get) Aug 15th 2012 +Steven Libby provided patch for #6 (Allow finer control over fallback mode selection) Aug 21th 2012 diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java b/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java index 1db1dac020536a03641cbb786b1b55aa88ef82f1..b93a4d7b1a9607f736666c22bae8e165a9d39af9 100644 --- a/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java +++ b/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java @@ -42,6 +42,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; +import java.util.LinkedHashSet; +import java.util.Arrays; +import java.util.Iterator; import java.util.Map; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; @@ -335,13 +338,15 @@ public abstract class Kernel implements Cloneable{ } } */ + static EXECUTION_MODE getDefaultExecutionMode() { EXECUTION_MODE defaultExecutionMode = OpenCLJNI.getJNI().isOpenCLAvailable() ? GPU : JTP; String executionMode = Config.executionMode; if (executionMode != null) { try { - EXECUTION_MODE requestedExecutionMode = valueOf(executionMode.toUpperCase()); - logger.fine("requested execution mode = " + requestedExecutionMode); + EXECUTION_MODE requestedExecutionMode; + requestedExecutionMode = getExecutionModeFromString(executionMode).iterator().next(); + logger.fine("requested execution mode ="); if ((OpenCLJNI.getJNI().isOpenCLAvailable() && requestedExecutionMode.isOpenCL()) || !requestedExecutionMode.isOpenCL()) { defaultExecutionMode = requestedExecutionMode; @@ -351,24 +356,78 @@ public abstract class Kernel implements Cloneable{ } } - logger.fine("default execution mode = " + defaultExecutionMode); + logger.fine("default execution modes = " + defaultExecutionMode); return (defaultExecutionMode); } + static LinkedHashSet<EXECUTION_MODE> getDefaultExecutionModes() { + LinkedHashSet<EXECUTION_MODE> defaultExecutionModes = new LinkedHashSet<EXECUTION_MODE>(); + if(OpenCLJNI.getJNI().isOpenCLAvailable()) { + defaultExecutionModes.add(GPU); + defaultExecutionModes.add(JTP); + } else { + defaultExecutionModes.add(JTP); + } + String executionMode = Config.executionMode; + if (executionMode != null) { + try { + LinkedHashSet<EXECUTION_MODE> requestedExecutionModes; + requestedExecutionModes = EXECUTION_MODE.getExecutionModeFromString(executionMode); + logger.fine("requested execution mode ="); + for(EXECUTION_MODE mode : requestedExecutionModes) { + logger.fine(" " + mode); + } + if ((OpenCLJNI.getJNI().isOpenCLAvailable() + && EXECUTION_MODE.anyOpenCL(requestedExecutionModes)) + || !EXECUTION_MODE.anyOpenCL(requestedExecutionModes)) { + defaultExecutionModes = requestedExecutionModes; + } + } catch (Throwable t) { + // we will take the default + } + } + + logger.fine("default execution modes = " + defaultExecutionModes); + + for(EXECUTION_MODE e : defaultExecutionModes) + { + logger.warning("SETTING DEFAULT MODE: " + e.toString()); + } + + return (defaultExecutionModes); + } + + static LinkedHashSet<EXECUTION_MODE> getExecutionModeFromString(String executionMode) { + LinkedHashSet<EXECUTION_MODE> executionModes = new LinkedHashSet<EXECUTION_MODE>(); + for(String mode : executionMode.split(",")) { + executionModes.add(valueOf(mode.toUpperCase())); + } + return executionModes; + } + static EXECUTION_MODE getFallbackExecutionMode() { EXECUTION_MODE defaultFallbackExecutionMode = JTP; logger.info("fallback execution mode = " + defaultFallbackExecutionMode); return (defaultFallbackExecutionMode); } + + static boolean anyOpenCL(LinkedHashSet<EXECUTION_MODE> _executionModes) { + for(EXECUTION_MODE mode : _executionModes) { + if(mode == GPU || mode== CPU) { + return true; + } + } + return false; + } + boolean isOpenCL() { return this == GPU || this == CPU; } }; - private EXECUTION_MODE executionMode = EXECUTION_MODE.getDefaultExecutionMode(); int[] globalId = new int[] { 0, @@ -2126,4 +2185,35 @@ public abstract class Kernel implements Cloneable{ return (kernelRunner.getProfileInfo()); } + private LinkedHashSet<EXECUTION_MODE> executionModes = EXECUTION_MODE.getDefaultExecutionModes(); + private Iterator<EXECUTION_MODE> currentMode = executionModes.iterator(); + private EXECUTION_MODE executionMode = currentMode.next(); + + /** + * set possible fallback path for execution modes. + * for example setExecutionFallbackPath(GPU,CPU,JTP) will try to use the GPU + * if it fails it will fall back to OpenCL CPU and finally it will try JTP. + */ + public void addExecutionModes(EXECUTION_MODE... platforms) { + executionModes.addAll(Arrays.asList(platforms)); + currentMode = executionModes.iterator(); + executionMode = currentMode.next(); + } + + /** + * @return is there another execution path we can try + */ + public boolean hasNextExecutionMode() { + return currentMode.hasNext(); + } + + /** + * try the next execution path in the list if there aren't any more than give up + */ + public void tryNextExecutionMode() { + if(currentMode.hasNext()) { + executionMode = currentMode.next(); + } + } + } diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java b/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java index 75e5a9731f7c2c9e0eafe0cb07eb393c8b5d936c..62ac74df1650e42c038f203a5ba8975a71673e7d 100644 --- a/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java +++ b/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java @@ -1332,8 +1332,12 @@ class KernelRunner{ } synchronized private Kernel fallBackAndExecute(String _entrypointName, final Range _range, final int _passes) { + if(kernel.hasNextExecutionMode()) { + kernel.tryNextExecutionMode(); + } else { + kernel.setFallbackExecutionMode(); + } - kernel.setFallbackExecutionMode(); return execute(_entrypointName, _range, _passes); }