Add openCL support
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ public class Configuration {
|
||||
private int priority;
|
||||
private ComputeType computeMethod;
|
||||
private GPUDevice GPUDevice;
|
||||
private boolean detectGPUs;
|
||||
private boolean printLog;
|
||||
public List<Pair<Calendar, Calendar>> 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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -92,7 +92,7 @@ public class SettingsLoader {
|
||||
}
|
||||
|
||||
if (gpu_ != null) {
|
||||
gpu = gpu_.getCudaName();
|
||||
gpu = gpu_.getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<GPUDevice> devices = null;
|
||||
|
||||
public static boolean generate() {
|
||||
devices = new LinkedList<GPUDevice>();
|
||||
List<GPUDevice> 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<Integer, GPUDevice> devicesWithPciId = new HashMap<Integer, GPUDevice>(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<Integer, GPUDevice> 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<GPUDevice> listDevices() {
|
||||
public static List<GPUDevice> listDevices(Configuration config) {
|
||||
if (devices == null) {
|
||||
generate();
|
||||
if (config.getDetectGPUs()) {
|
||||
generate();
|
||||
}
|
||||
else {
|
||||
devices = new LinkedList<GPUDevice>();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
7
src/com/sheepit/client/hardware/gpu/GPULister.java
Normal file
7
src/com/sheepit/client/hardware/gpu/GPULister.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package com.sheepit.client.hardware.gpu;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface GPULister {
|
||||
public abstract List<GPUDevice> getGpus();
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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:
|
||||
@@ -26,7 +26,7 @@
|
||||
*/
|
||||
|
||||
//package jcuda.driver;
|
||||
package com.sheepit.client.hardware.gpu;
|
||||
package com.sheepit.client.hardware.gpu.nvidia;
|
||||
|
||||
/**
|
||||
* Error codes.<br />
|
||||
123
src/com/sheepit/client/hardware/gpu/nvidia/Nvidia.java
Normal file
123
src/com/sheepit/client/hardware/gpu/nvidia/Nvidia.java
Normal file
@@ -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<GPUDevice> 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<GPUDevice> devices = new LinkedList<GPUDevice>();
|
||||
|
||||
HashMap<Integer, GPUDevice> devicesWithPciId = new HashMap<Integer, GPUDevice>(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<Integer, GPUDevice> entry : devicesWithPciId.entrySet()){
|
||||
GPUDevice aDevice = entry.getValue();
|
||||
aDevice.setId(TYPE + "_" + Integer.toString(i));
|
||||
devices.add(aDevice);
|
||||
i++;
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
}
|
||||
161
src/com/sheepit/client/hardware/gpu/opencl/OpenCL.java
Normal file
161
src/com/sheepit/client/hardware/gpu/opencl/OpenCL.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Laurent CLOUET
|
||||
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
|
||||
*
|
||||
* 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<GPUDevice> 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<GPUDevice> available_devices = new ArrayList<GPUDevice>(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();
|
||||
}
|
||||
}
|
||||
80
src/com/sheepit/client/hardware/gpu/opencl/OpenCLLib.java
Normal file
80
src/com/sheepit/client/hardware/gpu/opencl/OpenCLLib.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Laurent CLOUET
|
||||
* Author Laurent CLOUET <laurent.clouet@nopnop.net>
|
||||
*
|
||||
* 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<String> 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<String> getFieldOrder() {
|
||||
return Arrays.asList(new String[] { "id" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<T> extends OptionHandler<T> {
|
||||
|
||||
@Override
|
||||
public int parseArguments(Parameters params) throws CmdLineException {
|
||||
List<GPUDevice> gpus = GPU.listDevices();
|
||||
List<GPUDevice> 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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -99,7 +99,7 @@ public class Settings implements Activity {
|
||||
Configuration config = parent.getConfiguration();
|
||||
new SettingsLoader().merge(config);
|
||||
|
||||
List<GPUDevice> gpus = GPU.listDevices();
|
||||
List<GPUDevice> 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user