【发布时间】:2020-10-19 19:36:05
【问题描述】:
我在 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 检查 OpenCL 函数的每个返回,并在没有返回 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 中,代码会产生相同的输出(并且未安装时找到平台!),而在 jar 中运行时未找到平台。
我尝试了几种不同的 JRE,但在 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);
}
}
}
【问题讨论】:
-
在 IDE 下似乎只检测到 Mesa icd,而不是 Nvidia。您是否以其他(前提升的)用户身份运行 intellij?
-
已解决,见下文,但无论如何感谢您说出没有您我不会尝试的事情
-
不要编辑问题以表明它已解决。请改为阅读此内容:stackoverflow.com/help/someone-answers您可以接受自己的答案。
标签: java intellij-idea opencl lwjgl