最近想实现一个用java监控GPU的使用情况,但是java没有直接提供相关的api,在网上搜了好多帖子,最终参考了一篇实现了相关功能:参考文献
下面展示整个实现过程
package com.zyh.auto_tool.business.util;
import com.zyh.auto_tool.business.SystemTest.GpuInfo;
import com.zyh.auto_tool.business.execption.BizException;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* @author Jdb
* @date 2022/1/21 16:00
* @desc
*/
@Slf4j
public class GetGpu {
public static List<GpuInfo> getGPUUsagePercentage() throws IOException {
Process process = null;
try {
if (JudgeSystem.isWindows()){
long l = System.currentTimeMillis();
process = Runtime.getRuntime().exec("nvidia-smi.exe");
long l1 = System.currentTimeMillis();
log.info("Java调用程序耗时:{}毫秒",l1-l);
}else if (JudgeSystem.isLinux()){
String[] shell = {"/bin/bash", "-c", "nvidia-smi"};
process = Runtime.getRuntime().exec(shell);
}else {
throw new BizException(9999,"不在系统支持范围内");
}
process.getOutputStream().close();
} catch (Exception e) {
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = "";
while (null != (line = reader.readLine())) {
stringBuffer.append(line + "\n");
}
String gpus = null ;
gpus = stringBuffer.toString();
//分割废物信息
String[] split = gpus.split("\\|===============================\\+======================\\+======================\\|");
String[] gpusInfo = split[1].split(" ");
// 分割多个gpu
String[] gpuInfo = gpusInfo[0].split("\\+-------------------------------\\+----------------------\\+----------------------\\+");
List<GpuInfo> gpuInfoList = new ArrayList<>();
for (int i = 0; i < gpuInfo.length - 1; i++) {
GpuInfo gpuInfo1 = new GpuInfo();
String[] nameAndInfo = gpuInfo[i].split("\n");
//只要第二块的数据
String[] split1 = nameAndInfo[1].split("\\|")[1] // 0 TITAN V Off
.split("\\s+");//去空格
gpuInfo1.setNumber(Integer.parseInt(split1[1]));
StringBuffer name = new StringBuffer();
for (int j = 0; j < split1.length - 1; j++) {
if (j > 1 && j != split1.length) {
name.append(split1[j] + " ");
}
}
gpuInfo1.setName(name.toString());
String[] info = nameAndInfo[2].split("\\|")[2].split("\\s+");
gpuInfo1.setUsedMemory(info[1]);
gpuInfo1.setTotalMemory(info[3]);
int useable = Integer.parseInt(gpuInfo1.getTotalMemory().split("MiB")[0]) - Integer.parseInt(gpuInfo1.getUsedMemory().split("MiB")[0]);
gpuInfo1.setUseAbleMemory(useable + "MiB");
Double usageRate = Integer.parseInt(gpuInfo1.getUsedMemory().split("MiB")[0]) * 100.00 / Integer.parseInt(gpuInfo1.getTotalMemory().split("MiB")[0]);
gpuInfo1.setUsageRate(usageRate);
gpuInfoList.add(gpuInfo1);
}
return gpuInfoList;
}
public static void main(String[] args) throws IOException {
System.out.println(getGPUUsagePercentage());
}
}
package com.zyh.auto_tool.business.util;
import org.springframework.stereotype.Component;
/**
* @author Jdb
* @date 2022/1/21 15:31
* @desc
*/
@Component
public class JudgeSystem {
public static boolean isWindows(){
return System.getProperty("os.name").toLowerCase().contains("windows");
}
public static boolean isLinux(){
return System.getProperty("os.name").toLowerCase().contains("linux");
}
}
package com.zyh.auto_tool.business.SystemTest;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author Jdb
* @date 2022/1/21 15:59
* @desc
*/
@Data
public class GpuInfo {
@ApiModelProperty("GPU编号")
private Integer number;
@ApiModelProperty("显卡名称")
private String name;
@ApiModelProperty("总内存")
private String totalMemory;
@ApiModelProperty("使用内存")
private String usedMemory;
@ApiModelProperty("可用内存")
private String useAbleMemory;
@ApiModelProperty("使用率")
private Double usageRate;
}
其实现原理,最终还是通过java去调用c语言程序Runtime.getRuntime().exec(“nvidia-smi.exe”);
故监控硬件相关信息,还是通过C语言比较方便。