LWJGL 在 IDE 之外运行时发现不同的 OpenCL 安装
LWJGL finding different OpenCL installation when runing outside of IDE
我在 IntelliJ 中使用 java 作为一种爱好已经有一段时间了,并决定开始使用 OpenCL 进行并行计算。我很确定我在下载 LWJGL 库并将其添加到我的项目时没有出错,因为它总是可以编译。问题是当我 运行 程序时,它产生这个输出:
Platforms found: 1
Treating platform 140038554960288
Platform name: Clover
Platform vendor: Mesa
Platform version: OpenCL 1.1 Mesa 20.1.5
Error: -1
Exception in thread "main" java.lang.AssertionError: -1
at ch.test.Test1.devices_gpu(Test1.java:71)
at ch.test.Test1.treatPlatform(Test1.java:22)
at ch.test.Test1.main(Test1.java:94)
程序使用 assert
检查每个 return 的 OpenCL 函数,如果没有 return CL_SUCCESS,则程序崩溃。这里的错误是CL_DEVICE_NOT_FOUND.
当我将项目导出为 jar 并 运行 它在我的 IDE 中时,它会产生相同的输出。但是,如果我将发出的命令 (/home/user/Downloads/jdk-14.0.2/bin/java -ea -Dfile.encoding=UTF-8 -jar /home/user/IdeaProjects/LWJGLTest/out/artifacts/LWJGLTest_jar/LWJGLTest.jar
) 复制到控制台并 运行 那里的 jar,它会给我以下(预期的)输出:
user@user-desktop:~$ /home/user/Downloads/jdk-14.0.2/bin/java -ea -Dfile.encoding=UTF-8 -jar /home/user/IdeaProjects/LWJGLTest/out/artifacts/LWJGLTest_jar/LWJGLTest.jar
Platforms found: 1
Treating platform 140169617041680
Platform name: NVIDIA CUDA
Platform vendor: NVIDIA Corporation
Platform version: OpenCL 1.2 CUDA 10.2.178
Error: 0
1
Devices found: 1
Name: GeForce GTX 1080
我使用 clinfo
查看我的计算机找到了哪些 OpenCL 平台:
user@user-desktop:~$ clinfo
Number of platforms 1
Platform Name NVIDIA CUDA
Platform Vendor NVIDIA Corporation
Platform Version OpenCL 1.2 CUDA 11.0.228
Platform Profile FULL_PROFILE
Platform Extensions cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll cl_nv_copy_opts cl_nv_create_buffer cl_khr_int64_base_atomics cl_khr_int64_extended_atomics
Platform Extensions function suffix NV
Platform Name NVIDIA CUDA
Number of devices 1
Device Name GeForce GTX 1080
...
有趣的是,当我更改驱动程序(从开源到专有,反之亦然)时,clinfo
暂时找不到任何平台(当然直到我重新启动),但在 IntelliJ 中,代码生成相同的输出(并在安装 none 时找到平台!),而在 jar 中 运行 时未找到平台。
我尝试了几种不同的 JRE,但 none 在 IntelliJ 中工作。我也尝试过更改类路径,但似乎没有任何效果。
这一切都在 Linux Mint 19 下。当我在笔记本电脑上使用 Windows 执行相同操作时,没有任何问题,一切正常。
用于测试的代码:
package ch.test;
import org.lwjgl.PointerBuffer;
import org.lwjgl.opencl.CL22;
import java.nio.ByteBuffer;
public class Test1 {
static int getNumOfPlatforms() {
int[] buffer = new int[1];
int error = CL22.clGetPlatformIDs(null, buffer);
assert error == CL22.CL_SUCCESS;
return buffer[0];
}
static void treatPlatform(long plat) {
System.out.println("\tPlatform name: " + getPlatformParam(plat, CL22.CL_PLATFORM_NAME));
System.out.println("\tPlatform vendor: " + getPlatformParam(plat, CL22.CL_PLATFORM_VENDOR));
System.out.println("\tPlatform version: " + getPlatformParam(plat, CL22.CL_PLATFORM_VERSION));
PointerBuffer devices = devices_gpu(plat);
System.out.println("\tDevices found: " + devices.capacity());
while(devices.hasRemaining()) {
treatDevice(devices.get());
}
}
static void treatDevice(long device) {
System.out.println("\t\tName: " + deviceProperty(device, CL22.CL_DEVICE_NAME));
}
static String deviceProperty(long device, int prop) {
PointerBuffer length = PointerBuffer.allocateDirect(1);
CL22.clGetDeviceInfo(device, prop, (long[])null, length);
ByteBuffer value = ByteBuffer.allocateDirect((int)length.get());
CL22.clGetDeviceInfo(device, prop, value, null);
StringBuilder builder = new StringBuilder(value.capacity());
for(int i = 0; i < builder.capacity(); i++){
builder.append((char)value.get());
}
return builder.toString();
}
static String getPlatformParam(long plat, int attr) {
PointerBuffer length = PointerBuffer.allocateDirect(1);
CL22.clGetPlatformInfo(plat, attr, (long[])null, length);
ByteBuffer value = ByteBuffer.allocateDirect((int)length.get());
CL22.clGetPlatformInfo(plat, attr, value, null);
StringBuilder builder = new StringBuilder(value.capacity());
for(int i = 0; i < builder.capacity(); i++){
builder.append((char)value.get());
}
return builder.toString();
}
static PointerBuffer devices_gpu(long plat) {
int error;
int[] amount = new int[]{-1};
error = CL22.clGetDeviceIDs(plat, CL22.CL_DEVICE_TYPE_ALL, null, amount);
System.out.println("Error: " + error);
assert error == CL22.CL_SUCCESS: error;
System.out.println(amount[0]);
PointerBuffer devices = PointerBuffer.allocateDirect(amount[0]);
error = CL22.clGetDeviceIDs(plat, CL22.CL_DEVICE_TYPE_ALL, devices, (int[])null);
assert error == CL22.CL_SUCCESS: error;
return devices;
}
public static void main(String[] args) {
int error;
int amountOfPlatforms = getNumOfPlatforms();
System.out.println("Platforms found: " + amountOfPlatforms);
PointerBuffer platforms = PointerBuffer.allocateDirect(amountOfPlatforms);
error = CL22.clGetPlatformIDs(platforms, (int[])null);
assert error == CL22.CL_SUCCESS;
while(platforms.hasRemaining()) {
long plat = platforms.get();
System.out.println("Treating platform " + plat);
treatPlatform(plat);
}
}
}
虽然我没有找到确切的问题,但我通过从他们的网站重新安装 IntelliJ 解决了这个问题。看来我之前通过 Linux Mint Software Manager 完成的安装有问题。现在一切都很好
感谢阅读和帮助
我在 IntelliJ 中使用 java 作为一种爱好已经有一段时间了,并决定开始使用 OpenCL 进行并行计算。我很确定我在下载 LWJGL 库并将其添加到我的项目时没有出错,因为它总是可以编译。问题是当我 运行 程序时,它产生这个输出:
Platforms found: 1
Treating platform 140038554960288
Platform name: Clover
Platform vendor: Mesa
Platform version: OpenCL 1.1 Mesa 20.1.5
Error: -1
Exception in thread "main" java.lang.AssertionError: -1
at ch.test.Test1.devices_gpu(Test1.java:71)
at ch.test.Test1.treatPlatform(Test1.java:22)
at ch.test.Test1.main(Test1.java:94)
程序使用 assert
检查每个 return 的 OpenCL 函数,如果没有 return CL_SUCCESS,则程序崩溃。这里的错误是CL_DEVICE_NOT_FOUND.
当我将项目导出为 jar 并 运行 它在我的 IDE 中时,它会产生相同的输出。但是,如果我将发出的命令 (/home/user/Downloads/jdk-14.0.2/bin/java -ea -Dfile.encoding=UTF-8 -jar /home/user/IdeaProjects/LWJGLTest/out/artifacts/LWJGLTest_jar/LWJGLTest.jar
) 复制到控制台并 运行 那里的 jar,它会给我以下(预期的)输出:
user@user-desktop:~$ /home/user/Downloads/jdk-14.0.2/bin/java -ea -Dfile.encoding=UTF-8 -jar /home/user/IdeaProjects/LWJGLTest/out/artifacts/LWJGLTest_jar/LWJGLTest.jar
Platforms found: 1
Treating platform 140169617041680
Platform name: NVIDIA CUDA
Platform vendor: NVIDIA Corporation
Platform version: OpenCL 1.2 CUDA 10.2.178
Error: 0
1
Devices found: 1
Name: GeForce GTX 1080
我使用 clinfo
查看我的计算机找到了哪些 OpenCL 平台:
user@user-desktop:~$ clinfo
Number of platforms 1
Platform Name NVIDIA CUDA
Platform Vendor NVIDIA Corporation
Platform Version OpenCL 1.2 CUDA 11.0.228
Platform Profile FULL_PROFILE
Platform Extensions cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll cl_nv_copy_opts cl_nv_create_buffer cl_khr_int64_base_atomics cl_khr_int64_extended_atomics
Platform Extensions function suffix NV
Platform Name NVIDIA CUDA
Number of devices 1
Device Name GeForce GTX 1080
...
有趣的是,当我更改驱动程序(从开源到专有,反之亦然)时,clinfo
暂时找不到任何平台(当然直到我重新启动),但在 IntelliJ 中,代码生成相同的输出(并在安装 none 时找到平台!),而在 jar 中 运行 时未找到平台。
我尝试了几种不同的 JRE,但 none 在 IntelliJ 中工作。我也尝试过更改类路径,但似乎没有任何效果。
这一切都在 Linux Mint 19 下。当我在笔记本电脑上使用 Windows 执行相同操作时,没有任何问题,一切正常。 用于测试的代码:
package ch.test;
import org.lwjgl.PointerBuffer;
import org.lwjgl.opencl.CL22;
import java.nio.ByteBuffer;
public class Test1 {
static int getNumOfPlatforms() {
int[] buffer = new int[1];
int error = CL22.clGetPlatformIDs(null, buffer);
assert error == CL22.CL_SUCCESS;
return buffer[0];
}
static void treatPlatform(long plat) {
System.out.println("\tPlatform name: " + getPlatformParam(plat, CL22.CL_PLATFORM_NAME));
System.out.println("\tPlatform vendor: " + getPlatformParam(plat, CL22.CL_PLATFORM_VENDOR));
System.out.println("\tPlatform version: " + getPlatformParam(plat, CL22.CL_PLATFORM_VERSION));
PointerBuffer devices = devices_gpu(plat);
System.out.println("\tDevices found: " + devices.capacity());
while(devices.hasRemaining()) {
treatDevice(devices.get());
}
}
static void treatDevice(long device) {
System.out.println("\t\tName: " + deviceProperty(device, CL22.CL_DEVICE_NAME));
}
static String deviceProperty(long device, int prop) {
PointerBuffer length = PointerBuffer.allocateDirect(1);
CL22.clGetDeviceInfo(device, prop, (long[])null, length);
ByteBuffer value = ByteBuffer.allocateDirect((int)length.get());
CL22.clGetDeviceInfo(device, prop, value, null);
StringBuilder builder = new StringBuilder(value.capacity());
for(int i = 0; i < builder.capacity(); i++){
builder.append((char)value.get());
}
return builder.toString();
}
static String getPlatformParam(long plat, int attr) {
PointerBuffer length = PointerBuffer.allocateDirect(1);
CL22.clGetPlatformInfo(plat, attr, (long[])null, length);
ByteBuffer value = ByteBuffer.allocateDirect((int)length.get());
CL22.clGetPlatformInfo(plat, attr, value, null);
StringBuilder builder = new StringBuilder(value.capacity());
for(int i = 0; i < builder.capacity(); i++){
builder.append((char)value.get());
}
return builder.toString();
}
static PointerBuffer devices_gpu(long plat) {
int error;
int[] amount = new int[]{-1};
error = CL22.clGetDeviceIDs(plat, CL22.CL_DEVICE_TYPE_ALL, null, amount);
System.out.println("Error: " + error);
assert error == CL22.CL_SUCCESS: error;
System.out.println(amount[0]);
PointerBuffer devices = PointerBuffer.allocateDirect(amount[0]);
error = CL22.clGetDeviceIDs(plat, CL22.CL_DEVICE_TYPE_ALL, devices, (int[])null);
assert error == CL22.CL_SUCCESS: error;
return devices;
}
public static void main(String[] args) {
int error;
int amountOfPlatforms = getNumOfPlatforms();
System.out.println("Platforms found: " + amountOfPlatforms);
PointerBuffer platforms = PointerBuffer.allocateDirect(amountOfPlatforms);
error = CL22.clGetPlatformIDs(platforms, (int[])null);
assert error == CL22.CL_SUCCESS;
while(platforms.hasRemaining()) {
long plat = platforms.get();
System.out.println("Treating platform " + plat);
treatPlatform(plat);
}
}
}
虽然我没有找到确切的问题,但我通过从他们的网站重新安装 IntelliJ 解决了这个问题。看来我之前通过 Linux Mint Software Manager 完成的安装有问题。现在一切都很好 感谢阅读和帮助