diff --git a/CHANGELOG.md b/CHANGELOG.md index 1708c59001303a6c0065f911ce194eec8085417c..3fc672cc593ebd4f148306cb9d575496cd6971c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.10.0 * If statements with empty blocks and comparisons outside of if or while statements now compile and run on the GPU. +* Fix kernel management inconsistencies regarding preferred devices management ## 1.9.0 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 4e136b2ec1daf1ec72f35649b1769c5d64e69746..2c1464ec1fda8e941cbb1f6015ee16f7957266d9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -51,4 +51,5 @@ Below are some of the specific details of various contributions. * Luis Mendes submited PR to facilitate KernelManager class extension with non-static parameters in constructors * Luis Mendes submited PR to Enable kernel profiling and execution simultaneously on multiple devices * Luis Mendes submited PR to fix issue #78 - Signed integer constants were interpreted as unsigned values for instruction SIPUSH -* Luis Mendes submited PR to Support for OpenCLDevice configurator/configure API \ No newline at end of file +* Luis Mendes submited PR to Support for OpenCLDevice configurator/configure API +* Luis mendes submited PR to fix kernel management inconsistencies regarding preferred devices management \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6974b2db183d9b26803d592f1ed0865d1e0f1349..2d81ee4da58e2e075f39b0f0834a493757931e4c 100644 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,10 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <forkCount>4</forkCount> + <reuseForks>false</reuseForks> + </configuration> </plugin> <plugin> <groupId>org.jacoco</groupId> diff --git a/src/main/java/com/aparapi/internal/kernel/KernelManager.java b/src/main/java/com/aparapi/internal/kernel/KernelManager.java index 35a20e2c3a67d7e66b6672c2647e413dcec5738b..aff1d5ca183b51834eba43d54b66d72bab2c9020 100644 --- a/src/main/java/com/aparapi/internal/kernel/KernelManager.java +++ b/src/main/java/com/aparapi/internal/kernel/KernelManager.java @@ -36,7 +36,7 @@ import com.aparapi.internal.util.Reflection; public class KernelManager { private static KernelManager INSTANCE = new KernelManager(); - private LinkedHashMap<Integer, PreferencesWrapper> preferences = new LinkedHashMap<>(); + private LinkedHashMap<Class<? extends Kernel>, PreferencesWrapper> preferences = new LinkedHashMap<>(); private LinkedHashMap<Class<? extends Kernel>, KernelProfile> profiles = new LinkedHashMap<>(); private LinkedHashMap<Class<? extends Kernel>, Kernel> sharedInstances = new LinkedHashMap<>(); @@ -157,13 +157,13 @@ public class KernelManager { public KernelPreferences getPreferences(Kernel kernel) { synchronized (preferences) { - PreferencesWrapper wrapper = preferences.get(kernel.hashCode()); + PreferencesWrapper wrapper = preferences.get(kernel.getClass()); KernelPreferences kernelPreferences; if (wrapper == null) { kernelPreferences = new KernelPreferences(this, kernel.getClass()); - preferences.put(kernel.hashCode(), new PreferencesWrapper(kernel.getClass(), kernelPreferences)); + preferences.put(kernel.getClass(), new PreferencesWrapper(kernel.getClass(), kernelPreferences)); }else{ - kernelPreferences = preferences.get(kernel.hashCode()).getPreferences(); + kernelPreferences = preferences.get(kernel.getClass()).getPreferences(); } return kernelPreferences; } diff --git a/src/main/java/com/aparapi/internal/kernel/KernelPreferences.java b/src/main/java/com/aparapi/internal/kernel/KernelPreferences.java index 28f307dcf0ceca674e486949e5d22daae56b0dc9..2863e83c205e3afc0b85ca069f73b5ca1bdcdc20 100644 --- a/src/main/java/com/aparapi/internal/kernel/KernelPreferences.java +++ b/src/main/java/com/aparapi/internal/kernel/KernelPreferences.java @@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicReference; public class KernelPreferences { private final Class<? extends Kernel> kernelClass; private final KernelManager manager; - private final AtomicReference<LinkedList<Device>> preferredDevices = new AtomicReference<>(null); + private final AtomicReference<LinkedHashSet<Device>> preferredDevices = new AtomicReference<>(null); private final LinkedHashSet<Device> failedDevices = new LinkedHashSet<>(); public KernelPreferences(KernelManager manager, Class<? extends Kernel> kernelClass) { @@ -60,6 +60,24 @@ public class KernelPreferences { } return Collections.unmodifiableList(localPreferredDevices); } + + /** + * Validates if the specified devices is among the preferred devices for executing the kernel associated with the current + * kernel preferences. + * @param device the device to be tested + * @return <ul><li>true, if specified device is among the preferred devices</li> + * <li>false, otherwise</li></ul> + */ + public boolean isDeviceAmongPreferredDevices(Device device) { + maybeSetUpDefaultPreferredDevices(); + + boolean result = false; + synchronized (this) { + result = preferredDevices.get().contains(device); + } + + return result; + } synchronized void setPreferredDevices(LinkedHashSet<Device> _preferredDevices) { if (preferredDevices.get() != null) { @@ -67,7 +85,7 @@ public class KernelPreferences { preferredDevices.get().addAll(_preferredDevices); } else { - preferredDevices.set(new LinkedList<>(_preferredDevices)); + preferredDevices.set(new LinkedHashSet<>(_preferredDevices)); } failedDevices.clear(); } @@ -78,14 +96,23 @@ public class KernelPreferences { } synchronized void markPreferredDeviceFailed() { - if (preferredDevices.get().size() > 0) { - failedDevices.add(preferredDevices.get().remove(0)); + LinkedHashSet<Device> devices = preferredDevices.get(); + if (devices.size() > 0) { + Device device = devices.iterator().next(); + preferredDevices.get().remove(device); + failedDevices.add(device); } } + + synchronized void markDeviceFailed(Device device) { + preferredDevices.get().remove(device); + failedDevices.add(device); + } + private void maybeSetUpDefaultPreferredDevices() { if (preferredDevices.get() == null) { - preferredDevices.compareAndSet(null, new LinkedList<>(manager.getDefaultPreferences().getPreferredDevices(null))); + preferredDevices.compareAndSet(null, new LinkedHashSet<>(manager.getDefaultPreferences().getPreferredDevices(null))); } } diff --git a/src/main/java/com/aparapi/internal/kernel/KernelRunner.java b/src/main/java/com/aparapi/internal/kernel/KernelRunner.java index 58960925a578a0d2f327b2208178214f90754280..3c0386d216c3658dd857a0810a05964252dafe22 100644 --- a/src/main/java/com/aparapi/internal/kernel/KernelRunner.java +++ b/src/main/java/com/aparapi/internal/kernel/KernelRunner.java @@ -1309,7 +1309,7 @@ public class KernelRunner extends KernelRunnerJNI{ //This method is synchronized thus ensuring thread safety on concurrent executions of the same kernel class, //since preferences is shared between such threads. - preferences.markPreferredDeviceFailed(); + preferences.markDeviceFailed(device); // Device nextDevice = preferences.getPreferredDevice(kernel); // @@ -1750,7 +1750,7 @@ public class KernelRunner extends KernelRunnerJNI{ return false; } } else { - return (device == kernel.getTargetDevice()); + return KernelManager.instance().getPreferences(kernel).isDeviceAmongPreferredDevices(device); } }