diff --git a/protocol.txt b/protocol.txt index bbc2532..c028abd 100644 --- a/protocol.txt +++ b/protocol.txt @@ -79,6 +79,7 @@ Url: use the request type "request-job" from the configuration answer. Parameter as GET or POST: * computemethod: What compute types are available on this machine. 0 for CPU or GPU, 1 for CPU only, 2 for GPU only. * cpu_cores: Number of cores currently available for rendering (optional). + * gpu_type: GPU's type, usually CUDA or OPENCL * gpu_model: Model name of the GPU available for rendering * gpu_ram: GPU memory size (in bytes) diff --git a/src/com/sheepit/client/Configuration.java b/src/com/sheepit/client/Configuration.java index 70a5635..5eeaa2f 100644 --- a/src/com/sheepit/client/Configuration.java +++ b/src/com/sheepit/client/Configuration.java @@ -54,6 +54,7 @@ public class Configuration { private int priority; private ComputeType computeMethod; private GPUDevice GPUDevice; + private boolean detectGPUs; private boolean printLog; public List> requestTime; private String extras; @@ -76,6 +77,7 @@ public class Configuration { this.computeMethod = null; this.GPUDevice = null; this.userHasSpecifiedACacheDir = false; + this.detectGPUs = true; this.workingDirectory = null; this.storageDirectory = null; this.setCacheDir(cache_dir_); @@ -124,6 +126,10 @@ public class Configuration { return this.GPUDevice; } + public boolean getDetectGPUs() { + return this.detectGPUs; + } + public void setMaxUploadingJob(int max) { this.maxUploadingJob = max; } @@ -186,6 +192,10 @@ public class Configuration { this.GPUDevice = device; } + public void setDetectGPUs(boolean val) { + this.detectGPUs = val; + } + public void setComputeMethod(ComputeType meth) { this.computeMethod = meth; } diff --git a/src/com/sheepit/client/Job.java b/src/com/sheepit/client/Job.java index 0875e55..102c734 100644 --- a/src/com/sheepit/client/Job.java +++ b/src/com/sheepit/client/Job.java @@ -42,11 +42,13 @@ import java.util.TimerTask; import com.sheepit.client.Configuration.ComputeType; import com.sheepit.client.Error.Type; import com.sheepit.client.hardware.gpu.GPUDevice; +import com.sheepit.client.hardware.gpu.opencl.OpenCL; import com.sheepit.client.os.OS; public class Job { public static final String UPDATE_METHOD_BY_REMAINING_TIME = "remainingtime"; public static final String UPDATE_METHOD_BLENDER_INTERNAL_BY_PART = "blenderinternal"; + public static final String UPDATE_METHOD_BY_TILE = "by_tile"; private String numFrame; private String sceneMD5; @@ -236,7 +238,7 @@ public class Job { + " pass\n" + "signal.signal(signal.SIGINT, hndl)\n"; if (getUseGPU() && config.getGPUDevice() != null && config.getComputeMethod() != ComputeType.CPU) { - core_script = "sheepit_set_compute_device(\"CUDA\", \"GPU\", \"" + config.getGPUDevice().getCudaName() + "\")\n"; + core_script = "sheepit_set_compute_device(\"" + config.getGPUDevice().getType() + "\", \"GPU\", \"" + config.getGPUDevice().getId() + "\")\n"; gui.setComputeMethod("GPU"); } else { @@ -264,6 +266,11 @@ public class Job { new_env.put("PYTHONPATH", ""); // make sure blender is using the embedded python, if not it could create "Fatal Python error: Py_Initialize" new_env.put("PYTHONHOME", "");// make sure blender is using the embedded python, if not it could create "Fatal Python error: Py_Initialize" + if (getUseGPU() && config.getGPUDevice() != null && config.getComputeMethod() != ComputeType.CPU && OpenCL.TYPE.equals(config.getGPUDevice().getType())) { + new_env.put("CYCLES_OPENCL_SPLIT_KERNEL_TEST", "1"); + this.updateRenderingStatusMethod = UPDATE_METHOD_BY_TILE; // don't display remaining time + } + for (String arg : command1) { switch (arg) { case ".c": @@ -526,6 +533,28 @@ public class Job { } } } + else if (getUpdateRenderingStatusMethod() == null || getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BY_TILE)) { + String search = " Tile "; + int index = line.lastIndexOf(search); + if (index != -1) { + String buf = line.substring(index + search.length()); + String[] parts = buf.split("/"); + if (parts != null && parts.length == 2) { + try { + int current = Integer.parseInt(parts[0]); + int total = Integer.parseInt(parts[1]); + if (total != 0) { + gui.status(String.format("Rendering %s %%", (int) (100.0 * current / total))); + return; + } + } + catch (NumberFormatException e) { + System.out.println("Exception 94: " + e); + } + } + } + gui.status("Rendering"); + } } private void updateRenderingMemoryPeak(String line) { diff --git a/src/com/sheepit/client/Server.java b/src/com/sheepit/client/Server.java index 0a99ba2..c79a1ec 100644 --- a/src/com/sheepit/client/Server.java +++ b/src/com/sheepit/client/Server.java @@ -303,7 +303,7 @@ public class Server extends Thread implements HostnameVerifier, X509TrustManager } catch (UnsupportedEncodingException e) { } - url += "&gpu_model=" + gpu_model + "&gpu_ram=" + this.user_config.getGPUDevice().getMemory(); + url += "&gpu_model=" + gpu_model + "&gpu_ram=" + this.user_config.getGPUDevice().getMemory() + "&gpu_type=" + this.user_config.getGPUDevice().getType(); } connection = this.HTTPRequest(url, this.generateXMLForMD5cache()); diff --git a/src/com/sheepit/client/SettingsLoader.java b/src/com/sheepit/client/SettingsLoader.java index 3145db2..e39c8b7 100644 --- a/src/com/sheepit/client/SettingsLoader.java +++ b/src/com/sheepit/client/SettingsLoader.java @@ -92,7 +92,7 @@ public class SettingsLoader { } if (gpu_ != null) { - gpu = gpu_.getCudaName(); + gpu = gpu_.getId(); } } diff --git a/src/com/sheepit/client/hardware/gpu/GPU.java b/src/com/sheepit/client/hardware/gpu/GPU.java index d993d8e..9866d42 100644 --- a/src/com/sheepit/client/hardware/gpu/GPU.java +++ b/src/com/sheepit/client/hardware/gpu/GPU.java @@ -19,120 +19,31 @@ package com.sheepit.client.hardware.gpu; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; +import com.sheepit.client.Configuration; +import com.sheepit.client.hardware.gpu.nvidia.Nvidia; +import com.sheepit.client.hardware.gpu.opencl.OpenCL; import com.sheepit.client.os.OS; -import com.sun.jna.Native; -import com.sun.jna.ptr.IntByReference; -import com.sun.jna.ptr.LongByReference; +import com.sheepit.client.os.Windows; public class GPU { public static List devices = null; public static boolean generate() { devices = new LinkedList(); + List gpus = new Nvidia().getGpus(); + if (gpus != null) { + devices.addAll(gpus); + } OS os = OS.getOS(); - String path = os.getCUDALib(); - if (path == null) { - System.out.println("GPU::generate no CUDA lib path found"); - return false; - } - CUDA cudalib = null; - try { - cudalib = (CUDA) Native.loadLibrary(path, CUDA.class); - } - catch (java.lang.UnsatisfiedLinkError e) { - System.out.println("GPU::generate failed to load CUDA lib (path: " + path + ")"); - return false; - } - catch (java.lang.ExceptionInInitializerError e) { - System.out.println("GPU::generate ExceptionInInitializerError " + e); - return false; - } - catch (Exception e) { - System.out.println("GPU::generate generic exception " + e); - return false; - } - - int result = CUresult.CUDA_ERROR_UNKNOWN; - - result = cudalib.cuInit(0); - if (result != CUresult.CUDA_SUCCESS) { - System.out.println("GPU::generate cuInit failed (ret: " + result + ")"); - if (result == CUresult.CUDA_ERROR_UNKNOWN) { - System.out.println("If you are running Linux, this error is usually due to nvidia kernel module 'nvidia_uvm' not loaded."); - System.out.println("Relaunch the application as root or load the module."); - System.out.println("Most of time it does fix the issue."); + if (os instanceof Windows) { // opencl detection will crash on Mac (and sometimes on Linux) + gpus = new OpenCL().getGpus(); + if (gpus != null) { + devices.addAll(gpus); } - return false; - } - - if (result == CUresult.CUDA_ERROR_NO_DEVICE) { - return false; - } - - IntByReference count = new IntByReference(); - result = cudalib.cuDeviceGetCount(count); - - if (result != CUresult.CUDA_SUCCESS) { - System.out.println("GPU::generate cuDeviceGetCount failed (ret: " + CUresult.stringFor(result) + ")"); - return false; - } - - HashMap devicesWithPciId = new HashMap(count.getValue()); - for (int num = 0; num < count.getValue(); num++) { - IntByReference aDevice = new IntByReference(); - - result = cudalib.cuDeviceGet(aDevice, num); - if (result != CUresult.CUDA_SUCCESS) { - System.out.println("GPU::generate cuDeviceGet failed (ret: " + CUresult.stringFor(result) + ")"); - continue; - } - - IntByReference pciBusId = new IntByReference(); - result = cudalib.cuDeviceGetAttribute(pciBusId, CUDeviceAttribute.CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, aDevice.getValue()); - if (result != CUresult.CUDA_SUCCESS) { - System.out.println("GPU::generate cuDeviceGetAttribute for CU_DEVICE_ATTRIBUTE_PCI_BUS_ID failed (ret: " + CUresult.stringFor(result) + ")"); - continue; - } - - byte name[] = new byte[256]; - - result = cudalib.cuDeviceGetName(name, 256, num); - if (result != CUresult.CUDA_SUCCESS) { - System.out.println("GPU::generate cuDeviceGetName failed (ret: " + CUresult.stringFor(result) + ")"); - continue; - } - - LongByReference ram = new LongByReference(); - try { - result = cudalib.cuDeviceTotalMem_v2(ram, num); - } - catch (UnsatisfiedLinkError e) { - // fall back to old function - result = cudalib.cuDeviceTotalMem(ram, num); - } - - if (result != CUresult.CUDA_SUCCESS) { - System.out.println("GPU::generate cuDeviceTotalMem failed (ret: " + CUresult.stringFor(result) + ")"); - return false; - } - - devicesWithPciId.put(pciBusId.getValue(), new GPUDevice(new String(name).trim(), ram.getValue(), "FAKE")); - } - - // generate proper cuda id - // in theory a set to environment "CUDA_DEVICE_ORDER=PCI_BUS_ID" should be enough but it didn't work - int i = 0; - for (Map.Entry entry : devicesWithPciId.entrySet()){ - GPUDevice aDevice = entry.getValue(); - aDevice.setCudaName("CUDA_" + Integer.toString(i)); - devices.add(aDevice); - i++; } return true; @@ -150,9 +61,14 @@ public class GPU { return devs; } - public static List listDevices() { + public static List listDevices(Configuration config) { if (devices == null) { - generate(); + if (config.getDetectGPUs()) { + generate(); + } + else { + devices = new LinkedList(); + } } return devices; @@ -172,7 +88,7 @@ public class GPU { } for (GPUDevice dev : devices) { - if (device_model.equals(dev.getCudaName()) || device_model.equals(dev.getModel())) { + if (device_model.equals(dev.getId()) || device_model.equals(dev.getModel())) { return dev; } } diff --git a/src/com/sheepit/client/hardware/gpu/GPUDevice.java b/src/com/sheepit/client/hardware/gpu/GPUDevice.java index a9f3cf6..b138a51 100644 --- a/src/com/sheepit/client/hardware/gpu/GPUDevice.java +++ b/src/com/sheepit/client/hardware/gpu/GPUDevice.java @@ -20,15 +20,25 @@ package com.sheepit.client.hardware.gpu; public class GPUDevice { + private String type; private String model; private long memory; // in B - private String cudaName; + private String id; - public GPUDevice(String model, long ram, String cuda) { + public GPUDevice(String type, String model, long ram, String id) { + this.type = type; this.model = model; this.memory = ram; - this.cudaName = cuda; + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; } public String getModel() { @@ -47,17 +57,17 @@ public class GPUDevice { this.memory = memory; } - public String getCudaName() { - return cudaName; + public String getId() { + return id; } - public void setCudaName(String cudaName) { - this.cudaName = cudaName; + public void setId(String id) { + this.id = id; } @Override public String toString() { - return "GPUDevice [model=" + model + ", memory=" + memory + ", cudaName=" + cudaName + "]"; + return "GPUDevice [type=" + type + ", model='" + model + "', memory=" + memory + ", id=" + id + "]"; } public int getRecommandedTileSize() { diff --git a/src/com/sheepit/client/hardware/gpu/GPULister.java b/src/com/sheepit/client/hardware/gpu/GPULister.java new file mode 100644 index 0000000..8ef034c --- /dev/null +++ b/src/com/sheepit/client/hardware/gpu/GPULister.java @@ -0,0 +1,7 @@ +package com.sheepit.client.hardware.gpu; + +import java.util.List; + +public interface GPULister { + public abstract List getGpus(); +} diff --git a/src/com/sheepit/client/hardware/gpu/CUDA.java b/src/com/sheepit/client/hardware/gpu/nvidia/CUDA.java similarity index 96% rename from src/com/sheepit/client/hardware/gpu/CUDA.java rename to src/com/sheepit/client/hardware/gpu/nvidia/CUDA.java index e27a383..fbf17f8 100644 --- a/src/com/sheepit/client/hardware/gpu/CUDA.java +++ b/src/com/sheepit/client/hardware/gpu/nvidia/CUDA.java @@ -17,7 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package com.sheepit.client.hardware.gpu; +package com.sheepit.client.hardware.gpu.nvidia; import com.sun.jna.Library; import com.sun.jna.ptr.IntByReference; diff --git a/src/com/sheepit/client/hardware/gpu/CUDeviceAttribute.java b/src/com/sheepit/client/hardware/gpu/nvidia/CUDeviceAttribute.java similarity index 96% rename from src/com/sheepit/client/hardware/gpu/CUDeviceAttribute.java rename to src/com/sheepit/client/hardware/gpu/nvidia/CUDeviceAttribute.java index 39d1b22..2529e35 100644 --- a/src/com/sheepit/client/hardware/gpu/CUDeviceAttribute.java +++ b/src/com/sheepit/client/hardware/gpu/nvidia/CUDeviceAttribute.java @@ -17,7 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package com.sheepit.client.hardware.gpu; +package com.sheepit.client.hardware.gpu.nvidia; /** * CUDA Device properties. Taken directly from the online manual: diff --git a/src/com/sheepit/client/hardware/gpu/CUresult.java b/src/com/sheepit/client/hardware/gpu/nvidia/CUresult.java similarity index 99% rename from src/com/sheepit/client/hardware/gpu/CUresult.java rename to src/com/sheepit/client/hardware/gpu/nvidia/CUresult.java index 91d6db7..cca5d4c 100644 --- a/src/com/sheepit/client/hardware/gpu/CUresult.java +++ b/src/com/sheepit/client/hardware/gpu/nvidia/CUresult.java @@ -26,7 +26,7 @@ */ //package jcuda.driver; -package com.sheepit.client.hardware.gpu; +package com.sheepit.client.hardware.gpu.nvidia; /** * Error codes.
diff --git a/src/com/sheepit/client/hardware/gpu/nvidia/Nvidia.java b/src/com/sheepit/client/hardware/gpu/nvidia/Nvidia.java new file mode 100644 index 0000000..0d98b96 --- /dev/null +++ b/src/com/sheepit/client/hardware/gpu/nvidia/Nvidia.java @@ -0,0 +1,123 @@ +package com.sheepit.client.hardware.gpu.nvidia; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.sheepit.client.hardware.gpu.nvidia.CUDeviceAttribute; +import com.sheepit.client.hardware.gpu.GPUDevice; +import com.sheepit.client.hardware.gpu.GPULister; +import com.sheepit.client.os.OS; +import com.sun.jna.Native; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.LongByReference; + +public class Nvidia implements GPULister { + public static String TYPE = "CUDA"; + + @Override + public List getGpus() { + OS os = OS.getOS(); + String path = os.getCUDALib(); + if (path == null) { + return null; + } + CUDA cudalib = null; + try { + cudalib = (CUDA) Native.loadLibrary(path, CUDA.class); + } + catch (java.lang.UnsatisfiedLinkError e) { + return null; + } + catch (java.lang.ExceptionInInitializerError e) { + System.out.println("Nvidia::getGpus ExceptionInInitializerError " + e); + return null; + } + catch (Exception e) { + System.out.println("Nvidia::getGpus generic exception " + e); + return null; + } + + int result = CUresult.CUDA_ERROR_UNKNOWN; + + result = cudalib.cuInit(0); + if (result != CUresult.CUDA_SUCCESS) { + System.out.println("Nvidia::getGpus cuInit failed (ret: " + result + ")"); + if (result == CUresult.CUDA_ERROR_UNKNOWN) { + System.out.println("If you are running Linux, this error is usually due to nvidia kernel module 'nvidia_uvm' not loaded."); + System.out.println("Relaunch the application as root or load the module."); + System.out.println("Most of time it does fix the issue."); + } + return null; + } + + if (result == CUresult.CUDA_ERROR_NO_DEVICE) { + return null; + } + + IntByReference count = new IntByReference(); + result = cudalib.cuDeviceGetCount(count); + + if (result != CUresult.CUDA_SUCCESS) { + System.out.println("Nvidia::getGpus cuDeviceGetCount failed (ret: " + CUresult.stringFor(result) + ")"); + return null; + } + + List devices = new LinkedList(); + + HashMap devicesWithPciId = new HashMap(count.getValue()); + for (int num = 0; num < count.getValue(); num++) { + IntByReference aDevice = new IntByReference(); + + result = cudalib.cuDeviceGet(aDevice, num); + if (result != CUresult.CUDA_SUCCESS) { + System.out.println("Nvidia::getGpus cuDeviceGet failed (ret: " + CUresult.stringFor(result) + ")"); + continue; + } + + IntByReference pciBusId = new IntByReference(); + result = cudalib.cuDeviceGetAttribute(pciBusId, CUDeviceAttribute.CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, aDevice.getValue()); + if (result != CUresult.CUDA_SUCCESS) { + System.out.println("Nvidia::getGpus cuDeviceGetAttribute for CU_DEVICE_ATTRIBUTE_PCI_BUS_ID failed (ret: " + CUresult.stringFor(result) + ")"); + continue; + } + + byte name[] = new byte[256]; + + result = cudalib.cuDeviceGetName(name, 256, num); + if (result != CUresult.CUDA_SUCCESS) { + System.out.println("Nvidia::getGpus cuDeviceGetName failed (ret: " + CUresult.stringFor(result) + ")"); + continue; + } + + LongByReference ram = new LongByReference(); + try { + result = cudalib.cuDeviceTotalMem_v2(ram, num); + } + catch (UnsatisfiedLinkError e) { + // fall back to old function + result = cudalib.cuDeviceTotalMem(ram, num); + } + + if (result != CUresult.CUDA_SUCCESS) { + System.out.println("Nvidia::getGpus cuDeviceTotalMem failed (ret: " + CUresult.stringFor(result) + ")"); + return null; + } + + devicesWithPciId.put(pciBusId.getValue(), new GPUDevice(TYPE, new String(name).trim(), ram.getValue(), "FAKE")); + } + + // generate proper cuda id + // in theory a set to environment "CUDA_DEVICE_ORDER=PCI_BUS_ID" should be enough but it didn't work + int i = 0; + for (Map.Entry entry : devicesWithPciId.entrySet()){ + GPUDevice aDevice = entry.getValue(); + aDevice.setId(TYPE + "_" + Integer.toString(i)); + devices.add(aDevice); + i++; + } + return devices; + } + +} diff --git a/src/com/sheepit/client/hardware/gpu/opencl/OpenCL.java b/src/com/sheepit/client/hardware/gpu/opencl/OpenCL.java new file mode 100644 index 0000000..294a05a --- /dev/null +++ b/src/com/sheepit/client/hardware/gpu/opencl/OpenCL.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2013-2014 Laurent CLOUET + * Author Laurent CLOUET + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package com.sheepit.client.hardware.gpu.opencl; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +import com.sheepit.client.hardware.gpu.GPUDevice; +import com.sheepit.client.hardware.gpu.GPULister; +import com.sheepit.client.hardware.gpu.opencl.OpenCLLib.CLDeviceId; +import com.sheepit.client.hardware.gpu.opencl.OpenCLLib.CLPlatformId; +import com.sun.jna.Native; +import com.sun.jna.ptr.IntByReference; + +public class OpenCL implements GPULister { + public static String TYPE = "OPENCL"; + + @Override + public List getGpus() { + OpenCLLib lib = null; + + String path = "OpenCL"; + try { + lib = (OpenCLLib) Native.loadLibrary(path, OpenCLLib.class); + } + catch (java.lang.UnsatisfiedLinkError e) { + System.out.println("OpenCL::getGpus failed(A) to load OpenCL lib (path: " + path + ")"); + return null; + } + catch (java.lang.ExceptionInInitializerError e) { + System.out.println("OpenCL::getGpus failed(B) ExceptionInInitializerError " + e); + return null; + } + catch (Exception e) { + System.out.println("OpenCL::getGpus failed(C) generic exception " + e); + return null; + } + + int status = -1; + + // get the number of platform + IntByReference number_platforms = new IntByReference(); + + status = lib.clGetPlatformIDs(0, null, number_platforms); + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("OpenCL::getGpus failed(D) status: " + status); + return null; + } + + // now we can create the platforms + + final OpenCLLib.CLPlatformId.ByReference e6ref = new OpenCLLib.CLPlatformId.ByReference(); + OpenCLLib.CLPlatformId.ByReference[] plateforms = (OpenCLLib.CLPlatformId.ByReference[]) e6ref.toArray(number_platforms.getValue()); + + status = lib.clGetPlatformIDs(number_platforms.getValue(), plateforms, null); + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("OpenCL::getGpus failed(E) status: " + status); + return null; + } + + List available_devices = new ArrayList(1); + // Devices are numbered consecutively across platforms. + int id = 0; + for (int i = 0; i < number_platforms.getValue(); i++) { + // get number of devices in platform + IntByReference device_count = new IntByReference(); + + status = lib.clGetDeviceIDs(plateforms[i], OpenCLLib.CL_DEVICE_TYPE_GPU, 0, null, device_count); + if (status == OpenCLLib.CL_DEVICE_NOT_FOUND) { + System.out.println("OpenCL::getGpus no device found on plateforms[" + i + "]"); + continue; + } + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("OpenCL::getGpus failed(F) status: " + status); + return null; + } + + final OpenCLLib.CLDeviceId.ByReference e6ref4 = new OpenCLLib.CLDeviceId.ByReference(); + + OpenCLLib.CLDeviceId.ByReference[] devices = (OpenCLLib.CLDeviceId.ByReference[]) e6ref4.toArray(device_count.getValue()); + + status = lib.clGetDeviceIDs(plateforms[i], OpenCLLib.CL_DEVICE_TYPE_GPU, device_count.getValue(), devices, null); + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("OpenCL::getGpus failed(G) status: " + status); + return null; + } + + for (int j = 0; j < device_count.getValue(); j++) { + String platform_vendor = getInfoPlatform(lib, plateforms[i], OpenCLLib.CL_PLATFORM_VENDOR); + if (platform_vendor != null && platform_vendor.toLowerCase().equals("advanced micro devices, inc.")) { // opencl is only used for amd gpus + String name = getInfodeviceString(lib, devices[j], OpenCLLib.CL_DEVICE_BOARD_NAME_AMD); + long vram = getInfodeviceLong(lib, devices[j], OpenCLLib.CL_DEVICE_GLOBAL_MEM_SIZE); + if (name != null && vram > 0) { + available_devices.add(new GPUDevice(TYPE, name, vram, TYPE + "_" + id)); + } + } + id++; + } + } + + return available_devices; + } + + private static String getInfodeviceString(OpenCLLib lib, CLDeviceId.ByReference device, int type) { + byte name[] = new byte[256]; + + int status = lib.clGetDeviceInfo(device, type, 256, name, null); + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("OpenCL::getInfodeviceString failed(H) status: " + status + " type: " + type); + return null; + } + + return new String(name).trim(); + } + + private static long getInfodeviceLong(OpenCLLib lib, CLDeviceId.ByReference device, int type) { + byte name[] = new byte[256]; + + int status = lib.clGetDeviceInfo(device, type, 256, name, null); + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("OpenCL::getInfodeviceLong failed(I) status: " + status + " type: " + type); + return -1; + } + + ByteBuffer wrapped = ByteBuffer.wrap(name); + wrapped.order(ByteOrder.LITTLE_ENDIAN); + + return wrapped.getLong(); + } + + private static String getInfoPlatform(OpenCLLib lib, CLPlatformId.ByReference platform, int type) { + byte name[] = new byte[256]; + + int status = lib.clGetPlatformInfo(platform, type, 256, name, null); + if (status != OpenCLLib.CL_SUCCESS) { + System.out.println("GPU::getInfoPlatform failed(J) status: " + status + " type: " + type); + return null; + } + + return new String(name).trim(); + } +} diff --git a/src/com/sheepit/client/hardware/gpu/opencl/OpenCLLib.java b/src/com/sheepit/client/hardware/gpu/opencl/OpenCLLib.java new file mode 100644 index 0000000..f9c23cc --- /dev/null +++ b/src/com/sheepit/client/hardware/gpu/opencl/OpenCLLib.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2013-2014 Laurent CLOUET + * Author Laurent CLOUET + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package com.sheepit.client.hardware.gpu.opencl; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Library; +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; + +public interface OpenCLLib extends Library { + // status + public static final int CL_SUCCESS = 0; + public static final int CL_DEVICE_NOT_FOUND = -1; + + public static final int CL_PLATFORM_VENDOR = 0x0903; + + // cl_device_type + public static final int CL_DEVICE_TYPE_DEFAULT = (1 << 0); + public static final int CL_DEVICE_TYPE_CPU = (1 << 1); + public static final int CL_DEVICE_TYPE_GPU = (1 << 2); + public static final int CL_DEVICE_TYPE_ACCELERATOR = (1 << 3); + public static final int CL_DEVICE_TYPE_CUSTOM = (1 << 4); + public static final int CL_DEVICE_TYPE_ALL = 0xFFFFFFFF; + + // cl_device_info + public static final int CL_DEVICE_NAME = 0x102B; + public static final int CL_DEVICE_GLOBAL_MEM_SIZE = 0x101F; + public static final int CL_DEVICE_BOARD_NAME_AMD = 0x4038; + + public int clGetPlatformIDs(int num_entries, CLPlatformId.ByReference[] platforms, IntByReference num_platforms); + + public int clGetPlatformInfo(CLPlatformId.ByReference platform, int param_name, long param_value_size, byte[] destination, long size_ret[]); + + public int clGetDeviceIDs(CLPlatformId.ByReference platform, int param_name, int num_entries, CLDeviceId.ByReference[] devices, IntByReference device_count); + + public int clGetDeviceInfo(CLDeviceId.ByReference device, int param_name, long param_value_size, byte[] destination, long size_ret[]); + + public static class CLPlatformId extends Structure { + public static class ByReference extends CLPlatformId implements Structure.ByReference { + } + + public int id; + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "id" }); + } + } + + public static class CLDeviceId extends Structure { + public static class ByReference extends CLDeviceId implements Structure.ByReference { + } + + public int id; + + @Override + protected List getFieldOrder() { + return Arrays.asList(new String[] { "id" }); + } + } +} diff --git a/src/com/sheepit/client/standalone/ListGpuParameterHandler.java b/src/com/sheepit/client/standalone/ListGpuParameterHandler.java index 66f603e..86f8884 100644 --- a/src/com/sheepit/client/standalone/ListGpuParameterHandler.java +++ b/src/com/sheepit/client/standalone/ListGpuParameterHandler.java @@ -28,6 +28,7 @@ import org.kohsuke.args4j.spi.OptionHandler; import org.kohsuke.args4j.spi.Parameters; import org.kohsuke.args4j.spi.Setter; +import com.sheepit.client.Configuration; import com.sheepit.client.hardware.gpu.GPU; import com.sheepit.client.hardware.gpu.GPUDevice; @@ -38,10 +39,10 @@ public class ListGpuParameterHandler extends OptionHandler { @Override public int parseArguments(Parameters params) throws CmdLineException { - List gpus = GPU.listDevices(); + List gpus = GPU.listDevices(new Configuration(null, null, null)); if (gpus != null) { for (GPUDevice gpu : gpus) { - System.out.println("CUDA Name : " + gpu.getCudaName()); + System.out.println("Id : " + gpu.getId()); System.out.println("Model : " + gpu.getModel()); System.out.println("Memory, MB: " + (int) (gpu.getMemory() / (1024 * 1024))); System.out.println(); diff --git a/src/com/sheepit/client/standalone/Worker.java b/src/com/sheepit/client/standalone/Worker.java index 1f3386e..f003b3b 100644 --- a/src/com/sheepit/client/standalone/Worker.java +++ b/src/com/sheepit/client/standalone/Worker.java @@ -40,6 +40,8 @@ import com.sheepit.client.SettingsLoader; import com.sheepit.client.ShutdownHook; import com.sheepit.client.hardware.gpu.GPU; import com.sheepit.client.hardware.gpu.GPUDevice; +import com.sheepit.client.hardware.gpu.nvidia.Nvidia; +import com.sheepit.client.hardware.gpu.opencl.OpenCL; import com.sheepit.client.network.Proxy; public class Worker { @@ -58,9 +60,12 @@ public class Worker { @Option(name = "-max-uploading-job", usage = "", metaVar = "1", required = false) private int max_upload = -1; - @Option(name = "-gpu", usage = "CUDA name of the GPU used for the render, for example CUDA_0", metaVar = "CUDA_0", required = false) + @Option(name = "-gpu", usage = "Name of the GPU used for the render, for example CUDA_0 for Nvidia or OPENCL_0 for AMD/Intel card", metaVar = "CUDA_0", required = false) private String gpu_device = null; + @Option(name = "--no-gpu", usage = "Don't detect GPUs", required = false) + private boolean no_gpu_detection = false; + @Option(name = "-compute-method", usage = "CPU: only use cpu, GPU: only use gpu, CPU_GPU: can use cpu and gpu (not at the same time) if -gpu is not use it will not use the gpu", metaVar = "CPU", required = false) private String method = null; @@ -128,6 +133,7 @@ public class Worker { Configuration config = new Configuration(null, login, password); config.setPrintLog(print_log); config.setUsePriority(priority); + config.setDetectGPUs(! no_gpu_detection); if (cache_dir != null) { File a_dir = new File(cache_dir); @@ -146,16 +152,22 @@ public class Worker { } if (gpu_device != null) { - String cuda_str = "CUDA_"; - if (gpu_device.startsWith(cuda_str) == false) { - System.err.println("CUDA_DEVICE should look like 'CUDA_X' where X is a number"); + if (gpu_device.startsWith(Nvidia.TYPE) == false && gpu_device.startsWith(OpenCL.TYPE) == false) { + System.err.println("CUDA_DEVICE should look like '" + Nvidia.TYPE + "_X' or '" + OpenCL.TYPE + "_X' where X is a number"); return; } + String family = ""; try { - Integer.parseInt(gpu_device.substring(cuda_str.length())); + if (gpu_device.startsWith(Nvidia.TYPE)) { + family = Nvidia.TYPE; + } + else if (gpu_device.startsWith(OpenCL.TYPE)) { + family = OpenCL.TYPE; + } + Integer.parseInt(gpu_device.substring(family.length() + 1)); // for the _ } catch (NumberFormatException en) { - System.err.println("CUDA_DEVICE should look like 'CUDA_X' where X is a number"); + System.err.println("Gpu device code should look like '" + family + "_X' where X is a number"); return; } GPUDevice gpu = GPU.getGPUDevice(gpu_device); diff --git a/src/com/sheepit/client/standalone/swing/activity/Settings.java b/src/com/sheepit/client/standalone/swing/activity/Settings.java index 2a38d07..b016831 100644 --- a/src/com/sheepit/client/standalone/swing/activity/Settings.java +++ b/src/com/sheepit/client/standalone/swing/activity/Settings.java @@ -99,7 +99,7 @@ public class Settings implements Activity { Configuration config = parent.getConfiguration(); new SettingsLoader().merge(config); - List gpus = GPU.listDevices(); + List gpus = GPU.listDevices(config); GridBagConstraints constraints = new GridBagConstraints(); int currentRow = 0; @@ -208,10 +208,10 @@ public class Settings implements Activity { for (GPUDevice gpu : gpus) { JCheckBoxGPU gpuCheckBox = new JCheckBoxGPU(gpu); - gpuCheckBox.setToolTipText(gpu.getCudaName()); + gpuCheckBox.setToolTipText(gpu.getId()); if (gpuChecked) { GPUDevice config_gpu = config.getGPUDevice(); - if (config_gpu != null && config_gpu.getCudaName().equals(gpu.getCudaName())) { + if (config_gpu != null && config_gpu.getId().equals(gpu.getId())) { gpuCheckBox.setSelected(gpuChecked); } }