diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37e7d6a41146cdf32f22283e2b8d005b1cff4a91..595a5a87e65af0bb9c669f63d4e27d5dbfff6699 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,13 @@
 # Aparapi Changelog
 
-## 1.8.1
+## 1.9.0
+
+* (JNI) Fixed local arrays handling 1D and ND, to cope with arrays resizing across kernel executions
+* Significant speed-up on discrete GPUs with dedicated memory - OpenCLDevice.setSharedMemory(false)
+* (JNI) Aparapi now supports efficient execution on discrete GPU and other devices with dedicated memory
+* Support for OpenCLDevice configurator/configure API
+
+* (JNI) Fixed local arrays handling 1D and ND, to cope with arrays resizing across kernel executions
 
 ## 1.8.0
 
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index e0ef9adb73474858e0c128a3fd6d24dd6628f7b4..4e136b2ec1daf1ec72f35649b1769c5d64e69746 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -50,4 +50,5 @@ Below are some of the specific details of various contributions.
 * Luis Mendes submited PR for issue #101 - Possible deadlock in JTP mode
 * 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
\ No newline at end of file
+* 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
diff --git a/pom.xml b/pom.xml
index 33c1e1c2fca2cc4fc92a64eb58cdc91471bced3e..0ab3609657868ca56e013fa7f01facd86a0caba0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
 
     <groupId>com.aparapi</groupId>
     <artifactId>aparapi</artifactId>
-    <version>1.8.1-SNAPSHOT</version>
+    <version>1.9.0-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <prerequisites>
diff --git a/src/main/java/com/aparapi/device/IOpenCLDeviceConfigurator.java b/src/main/java/com/aparapi/device/IOpenCLDeviceConfigurator.java
new file mode 100644
index 0000000000000000000000000000000000000000..38a8a8b41536940544e391ee15de7dd43bda14a3
--- /dev/null
+++ b/src/main/java/com/aparapi/device/IOpenCLDeviceConfigurator.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2016 - 2018 Syncleus, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.aparapi.device;
+
+/**
+ * This interface provides a way for the client application to refine the default devices
+ * configuration obtained by the underlying OpenCL platforms in a centralized, automated manner.<br/>
+ * 
+ * @author CoreRasurae
+ */
+public interface IOpenCLDeviceConfigurator {
+	
+	/**
+	 * Called for each OpenCL device detected by Aparapi.<br/>
+	 * Gives the client application an opportunity to refine the device configuration parameters.
+	 * 
+	 * @param device the OpenCL device to be configured
+	 */
+	public void configure(OpenCLDevice device);
+	
+}
diff --git a/src/main/java/com/aparapi/device/OpenCLDevice.java b/src/main/java/com/aparapi/device/OpenCLDevice.java
index a105540e54ba508c8dac8e79e5bfc7424d847de4..56cd1760ce081b386999ab09d6747c22905638f2 100644
--- a/src/main/java/com/aparapi/device/OpenCLDevice.java
+++ b/src/main/java/com/aparapi/device/OpenCLDevice.java
@@ -15,8 +15,6 @@
  */
 package com.aparapi.device;
 
-import com.aparapi.opencl.OpenCL.Kernel;
-
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -29,6 +27,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import com.aparapi.Range;
 import com.aparapi.internal.opencl.OpenCLArgDescriptor;
@@ -41,11 +40,14 @@ import com.aparapi.opencl.OpenCL.Constant;
 import com.aparapi.opencl.OpenCL.GlobalReadOnly;
 import com.aparapi.opencl.OpenCL.GlobalReadWrite;
 import com.aparapi.opencl.OpenCL.GlobalWriteOnly;
+import com.aparapi.opencl.OpenCL.Kernel;
 import com.aparapi.opencl.OpenCL.Local;
 import com.aparapi.opencl.OpenCL.Resource;
 import com.aparapi.opencl.OpenCL.Source;
 
 public class OpenCLDevice extends Device implements Comparable<Device> {
+	
+   private static IOpenCLDeviceConfigurator configurator = null;
 
    private final OpenCLPlatform platform;
 
@@ -58,11 +60,22 @@ public class OpenCLDevice extends Device implements Comparable<Device> {
    private long globalMemSize;
 
    private long maxMemAllocSize;
+   
+   private boolean sharedMemory = true;
 
    private String shortDescription = null;
 
    private String name = null;
 
+   private AtomicBoolean underConfiguration = new AtomicBoolean(false);
+   /**
+    * Statically assigns a new configurator for all OpenCL devices detected after the assignment. 
+    * @param _configurator the configurator instance
+    */
+   public static void setConfigurator(IOpenCLDeviceConfigurator _configurator) {
+	   configurator = _configurator;
+   }
+   
    /**
     * Minimal constructor
     *
@@ -112,7 +125,7 @@ public class OpenCLDevice extends Device implements Comparable<Device> {
       globalMemSize = _globalMemSize;
    }
 
-   void setMaxWorkItemSize(int _dim, int _value) {
+   public void setMaxWorkItemSize(int _dim, int _value) {
       maxWorkItemSize[_dim] = _value;
    }
 
@@ -124,10 +137,49 @@ public class OpenCLDevice extends Device implements Comparable<Device> {
     this.name = name;
   }
 
+  /**
+   * Called by the underlying Aparapi OpenCL platform, upon device
+   * detection.
+   */
+  public void configure() {
+	  if (configurator != null && !underConfiguration.get() &&
+			  underConfiguration.compareAndSet(false, true)) {
+		 configurator.configure(this);
+		 underConfiguration.set(false);
+	  }
+  }
+  
   @Override
   public long getDeviceId() {
       return (deviceId);
    }
+  
+  /**
+   * Configure if device has the memory shared with the host memory.
+   * <br/>
+   * <b>Note1: </b>For discrete GPU devices having dedicated memory, 
+   * thus not shared with host, this should be set to false. This can result
+   * in significant kernel execution speed-ups for such HW configurations.
+   * Aparapi is unable to detect this property automatically for all devices, unless
+   * the client application provides a configurator ({@link #IOpenCLDeviceConfigurator}). 
+   * <br/> 
+   * <b>Note2: </b>By default devices are initialized has having shared memory - to maintain
+   * backwards compatibility - unless Aparapi can unequivocally identify the device.
+   * @param _sharedMemory <ul><li>true, if OpenCL device has the memory shared with the host memory</li>
+   *             <li>false, if OpenCL device is a discrete unit, having dedicated memory, thus not shared with host</li></ul>
+   */
+  public void setSharedMemory(boolean _sharedMemory) {
+	  sharedMemory = _sharedMemory;
+  }
+  
+  /**
+   * Retrieves the shared memory flag 
+   * @return <ul><li>true, if OpenCL device has the memory shared with the host memory</li>
+   *             <li>false, if OpenCL device is a discrete unit, having dedicated memory, thus not shared with host</li></ul>   
+   */
+  public boolean isSharedMemory() {
+	  return sharedMemory;
+  }
 
    @Override
    public String getShortDescription() {
diff --git a/src/test/java/com/aparapi/runtime/MultiDimensionalLocalArrayTest.java b/src/test/java/com/aparapi/runtime/MultiDimensionalLocalArrayTest.java
index dd0cb0f58d12b7f23875049bd62f2686ccf6fc0d..8cc14518b82a5a9e7c8393711d7ed2baaceb40c0 100644
--- a/src/test/java/com/aparapi/runtime/MultiDimensionalLocalArrayTest.java
+++ b/src/test/java/com/aparapi/runtime/MultiDimensionalLocalArrayTest.java
@@ -117,6 +117,44 @@ public class MultiDimensionalLocalArrayTest
         assertEquals(3840, RESULT[0], 1E-6F);
     }
 
+    @Test
+    public void singleDimensionMultipleExecutionTest()
+    {
+    	final Device device = getDevice();
+        final int SIZE = 16;
+        final float[] RESULT = new float[2];
+        Kernel kernel = new Kernel()
+        {
+            @Local final float[] localArray = new float[SIZE*SIZE];
+
+            @Override
+            public void run()
+            {
+                int row = getGlobalId(0);
+                int column = getGlobalId(1);
+                localArray[row + column*SIZE] = row + column;
+                localBarrier();
+                float value = 0;
+                for (int x = 0; x < SIZE; x++)
+                {
+                    for (int y = 0; y < SIZE; y++)
+                    {
+                        value += localArray[x + y*SIZE];
+                    }
+                }
+                RESULT[0] = value;
+            }
+        };
+        try {
+        	kernel.execute(Range.create2D(device, SIZE, SIZE, SIZE, SIZE));
+        	assertEquals(3840, RESULT[0], 1E-6F);
+        	kernel.execute(Range.create2D(device, SIZE, SIZE, SIZE, SIZE));
+        	assertEquals(3840, RESULT[0], 1E-6F);
+        } finally {
+        	kernel.dispose();
+        }
+    }
+
     @Test
     public void twoDimensionTest()
     {
@@ -153,7 +191,6 @@ public class MultiDimensionalLocalArrayTest
         assertEquals(3840, RESULT[0][0], 1E-6F);        
     }
     
-    @Ignore("Aparapi fails to re-execute kernel with local NDarrays")
     @Test
     public void twoDimensionMultipleExecutionTest()
     {
@@ -267,7 +304,6 @@ public class MultiDimensionalLocalArrayTest
         }    	
     }
 
-    @Ignore("Aparapi-native fails to resize 1D arrays across executions")
     @Test
     public void resizableOneDimensionTest()
     {
@@ -283,14 +319,13 @@ public class MultiDimensionalLocalArrayTest
         	assertEquals(3840, RESULT[0], 1E-6F);
         	kernel.setArray(2*SIZE, new float[2*SIZE*2*SIZE]);
         	kernel.execute(Range.create2D(device, 2*SIZE, 2*SIZE, 2*SIZE, 2*SIZE));
-        	assertTrue("Result is not greater then 2840", RESULT[0]>3840);
+        	assertTrue("Result is not greater then 3840", RESULT[0]>3840);
         } finally {
         	kernel.dispose();
         }
         
     }
     
-    @Ignore("Aparapi-native fails to resize NDarray across kernel executions")
     @Test
     public void resizableTwoDimensionTest()
     {
@@ -305,7 +340,7 @@ public class MultiDimensionalLocalArrayTest
 	        assertEquals(3840, RESULT[0], 1E-6F);
 	        kernel.setArray(2*SIZE, new float[2*SIZE][2*SIZE]);
 	        kernel.execute(Range.create2D(device, SIZE, SIZE, SIZE, SIZE));
-	        assertTrue("Result is not greater than 2840", RESULT[0]>3840);
+	        assertTrue("Result is not greater than 3840", RESULT[0]>3840);
         } finally {
         	kernel.dispose();
         }
diff --git a/src/test/java/com/aparapi/runtime/OpenCLDeviceConfiguratorTest.java b/src/test/java/com/aparapi/runtime/OpenCLDeviceConfiguratorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..942dd2ef3dd37a1877adb47acec03bcd371a9757
--- /dev/null
+++ b/src/test/java/com/aparapi/runtime/OpenCLDeviceConfiguratorTest.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2016 - 2018 Syncleus, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.aparapi.runtime;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import com.aparapi.device.Device;
+import com.aparapi.device.IOpenCLDeviceConfigurator;
+import com.aparapi.device.OpenCLDevice;
+import com.aparapi.internal.kernel.KernelManager;
+import com.aparapi.internal.opencl.OpenCLPlatform;
+
+/**
+ * Tests for feature OpenCLDeviceConfigurator set 1/2 
+ * 
+ * @author CoreRasurae
+ */
+public class OpenCLDeviceConfiguratorTest {
+    private static OpenCLDevice openCLDevice = null;
+
+    private class CLKernelManager extends KernelManager {
+    	@Override
+    	protected List<Device.TYPE> getPreferredDeviceTypes() {
+    		return Arrays.asList(Device.TYPE.ACC, Device.TYPE.GPU, Device.TYPE.CPU);
+    	}
+    }
+        
+    public void setUp() throws Exception {
+    	KernelManager.setKernelManager(new CLKernelManager());
+        Device device = KernelManager.instance().bestDevice();
+        if (device == null || !(device instanceof OpenCLDevice)) {
+        	System.out.println("!!!No OpenCLDevice available for running the integration test");
+        }
+        assumeTrue (device != null && device instanceof OpenCLDevice);
+        openCLDevice = (OpenCLDevice) device;
+    }
+
+    public void setUpWithConfigurator(IOpenCLDeviceConfigurator configurator) throws Exception {
+    	OpenCLDevice.setConfigurator(configurator);
+    	setUp();
+    }
+    
+    @Test
+    public void configuratorCallbackTest() throws Exception {
+    	final AtomicInteger callCounter = new AtomicInteger(0);
+    	IOpenCLDeviceConfigurator configurator = new IOpenCLDeviceConfigurator() {
+			@Override
+			public void configure(OpenCLDevice device) {
+				callCounter.incrementAndGet();
+				device.setName("Configured");
+				device.setSharedMemory(false);
+			}
+    	};
+    	setUpWithConfigurator(configurator);
+    	assertTrue("Number of configured devices should be > 0", callCounter.get() > 0);
+    	int numberOfConfiguredDevices = callCounter.get();
+    	
+		assertFalse("Device isShareMempory() should return false", openCLDevice.isSharedMemory());
+		assertEquals("Device name should be \"Configured\"", "Configured", openCLDevice.getName());   
+    	
+    	int numberOfDevices = 0;
+    	List<OpenCLPlatform> platforms = OpenCLPlatform.getUncachedOpenCLPlatforms();
+    	for (OpenCLPlatform platform : platforms) {
+    		for (OpenCLDevice device : platform.getOpenCLDevices()) {
+    			assertFalse("Device isShareMempory() should return false", device.isSharedMemory());
+    			assertEquals("Device name should be \"Configured\"", "Configured", device.getName());
+    			numberOfDevices++;
+    		}
+    	}
+
+    	assertEquals("Number of configured devices should match numnber of devices", numberOfDevices, numberOfConfiguredDevices);
+    	assertEquals("Number of calls doesn't match the expected", numberOfDevices*2, callCounter.get());
+    }
+ }
diff --git a/src/test/java/com/aparapi/runtime/OpenCLDeviceNoConfiguratorTest.java b/src/test/java/com/aparapi/runtime/OpenCLDeviceNoConfiguratorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b640d5de1546ae93490e0eea89d8c9e90b77db11
--- /dev/null
+++ b/src/test/java/com/aparapi/runtime/OpenCLDeviceNoConfiguratorTest.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2016 - 2018 Syncleus, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.aparapi.runtime;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import com.aparapi.device.Device;
+import com.aparapi.device.IOpenCLDeviceConfigurator;
+import com.aparapi.device.OpenCLDevice;
+import com.aparapi.internal.kernel.KernelManager;
+import com.aparapi.internal.opencl.OpenCLPlatform;
+
+/**
+ * Tests for feature OpenCLDeviceConfigurator set 2/2 
+ * 
+ * @author CoreRasurae
+ */
+public class OpenCLDeviceNoConfiguratorTest {
+    private static OpenCLDevice openCLDevice = null;
+
+    private class CLKernelManager extends KernelManager {
+    	@Override
+    	protected List<Device.TYPE> getPreferredDeviceTypes() {
+    		return Arrays.asList(Device.TYPE.ACC, Device.TYPE.GPU, Device.TYPE.CPU);
+    	}
+    }
+        
+    public void setUp() throws Exception {
+    	KernelManager.setKernelManager(new CLKernelManager());
+        Device device = KernelManager.instance().bestDevice();
+        if (device == null || !(device instanceof OpenCLDevice)) {
+        	System.out.println("!!!No OpenCLDevice available for running the integration test");
+        }
+        assumeTrue (device != null && device instanceof OpenCLDevice);
+        openCLDevice = (OpenCLDevice) device;
+    }
+
+    @Test
+    public void noConfiguratorTest() throws Exception {
+    	setUp();
+    	assertTrue("Device isShareMempory() should return true", openCLDevice.isSharedMemory());
+		assertNotEquals("Device name should not be \"Configured\"", "Configured", openCLDevice.getName());
+    	List<OpenCLPlatform> platforms = OpenCLPlatform.getUncachedOpenCLPlatforms();
+    	for (OpenCLPlatform platform : platforms) {
+    		for (OpenCLDevice device : platform.getOpenCLDevices()) {
+    			assertTrue("Device isSharedMempory() should return true", device.isSharedMemory());
+    			assertNotEquals("Device name should not be \"Configured\"", "Configured", device.getName());
+    		}
+    	}
+    }
+    
+    @Test
+    public void protectionAgainstRecursiveConfiguresTest() {
+    	OpenCLDevice dev = new OpenCLDevice(null, 101L, Device.TYPE.CPU);
+    	final AtomicInteger callCounter = new AtomicInteger(0);
+    	IOpenCLDeviceConfigurator configurator = new IOpenCLDeviceConfigurator() {
+			@Override
+			public void configure(OpenCLDevice device) {
+				callCounter.incrementAndGet();
+				device.configure();
+			}
+    	};
+    	OpenCLDevice.setConfigurator(configurator);
+    	dev.configure();
+    	
+    	assertEquals("Number of confgure() calls should be one", 1, callCounter.get());
+    }
+}