Add cpu layout
This commit is contained in:
135
src/main/java/me/cortex/voxy/common/util/cpu/CpuLayout.java
Normal file
135
src/main/java/me/cortex/voxy/common/util/cpu/CpuLayout.java
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package me.cortex.voxy.common.util.cpu;
|
||||||
|
|
||||||
|
import com.sun.jna.platform.win32.Kernel32Util;
|
||||||
|
import com.sun.jna.platform.win32.WinNT;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import me.cortex.voxy.common.Logger;
|
||||||
|
import me.cortex.voxy.common.util.ThreadUtils;
|
||||||
|
import org.lwjgl.system.Platform;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
//Represents the layout of the current cpu running on
|
||||||
|
public class CpuLayout {
|
||||||
|
private CpuLayout(){}
|
||||||
|
|
||||||
|
public static void setThreadAffinity(Core... cores) {
|
||||||
|
var affinity = new Affinity[cores.length];
|
||||||
|
for (int i = 0; i < cores.length; i++) {
|
||||||
|
affinity[i] = cores[i].affinity;
|
||||||
|
}
|
||||||
|
setThreadAffinity(affinity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setThreadAffinity(Affinity... affinities) {
|
||||||
|
if (Platform.get() == Platform.WINDOWS) {
|
||||||
|
long[] msks = new long[affinities.length];
|
||||||
|
short[] groups = new short[affinities.length];Arrays.fill(groups, (short) -1);
|
||||||
|
int i = 0;
|
||||||
|
for (var a : affinities) {
|
||||||
|
int idx;
|
||||||
|
for (idx = 0; idx<i && groups[idx]!=a.group; idx++);
|
||||||
|
if (idx == i) {groups[idx] = a.group; i++;}
|
||||||
|
msks[idx] |= a.msk;
|
||||||
|
}
|
||||||
|
ThreadUtils.SetThreadSelectedCpuSetMasksWin32(Arrays.copyOf(msks, i), Arrays.copyOf(groups, i));
|
||||||
|
} else {
|
||||||
|
Logger.error("TODO: THIS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Core[] generateCoreLayoutWindows() {
|
||||||
|
var cores = Kernel32Util.getLogicalProcessorInformationEx(WinNT.LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore);
|
||||||
|
boolean allSameClass = true;
|
||||||
|
for (var coreO : cores) {
|
||||||
|
var core = (WinNT.PROCESSOR_RELATIONSHIP) coreO;
|
||||||
|
allSameClass &= core.efficiencyClass == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
var res = new Core[cores.length];
|
||||||
|
for (var coreO : cores) {
|
||||||
|
var core = (WinNT.PROCESSOR_RELATIONSHIP) coreO;
|
||||||
|
boolean smt = (core.flags&1)==1;
|
||||||
|
byte eclz = core.efficiencyClass;
|
||||||
|
if (core.groupMask.length!=1) {
|
||||||
|
throw new IllegalStateException("Unsupported architecture");
|
||||||
|
}
|
||||||
|
var msk = core.groupMask[0].mask.longValue();
|
||||||
|
if (Long.bitCount(msk)>1 != smt) {
|
||||||
|
throw new IllegalStateException("Logic issue");
|
||||||
|
}
|
||||||
|
res[i++] = new Core((!allSameClass)&&eclz==0, new Affinity(msk, core.groupMask[0].group));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Core[] generateCoreLayoutLinux() {
|
||||||
|
var processor = new SystemInfo().getHardware().getProcessor();
|
||||||
|
Int2ObjectOpenHashMap<Affinity> affinityMsk = new Int2ObjectOpenHashMap<>();
|
||||||
|
for (var thread : processor.getLogicalProcessors()) {
|
||||||
|
var aff = affinityMsk.getOrDefault(thread.getPhysicalProcessorNumber(), new Affinity(0, (short) thread.getProcessorGroup()));
|
||||||
|
if (thread.getProcessorGroup() != aff.group) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
affinityMsk.put(thread.getPhysicalProcessorNumber(), new Affinity(aff.msk|(1L<<thread.getProcessorNumber()), (short) thread.getProcessorGroup()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var cores = new Core[processor.getPhysicalProcessors().size()];
|
||||||
|
int i = 0;
|
||||||
|
boolean allSameEfficiency = true;
|
||||||
|
for (var core : processor.getPhysicalProcessors()) {
|
||||||
|
if (core.getEfficiency() != 0) {
|
||||||
|
allSameEfficiency = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var core : processor.getPhysicalProcessors()) {
|
||||||
|
var aff = affinityMsk.remove(core.getPhysicalProcessorNumber());
|
||||||
|
if (aff == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
cores[i++] = new Core(core.getEfficiency()==0&&!allSameEfficiency, aff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Affinity(long msk, short group) {}
|
||||||
|
public record Core(boolean isEfficiency, Affinity affinity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Core[] CORES;
|
||||||
|
static {
|
||||||
|
if (Platform.get() == Platform.WINDOWS) {
|
||||||
|
CORES = generateCoreLayoutWindows();
|
||||||
|
} else if (Platform.get() == Platform.LINUX) {
|
||||||
|
CORES = generateCoreLayoutLinux();
|
||||||
|
} else {
|
||||||
|
CORES = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
setThreadAffinity(CORES[0], CORES[1]);
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
int finalI = i;
|
||||||
|
new Thread(()->{
|
||||||
|
setThreadAffinity(CORES[finalI&3]);
|
||||||
|
Random r = new Random();
|
||||||
|
int j= 0;
|
||||||
|
while (r.nextLong()!=0) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
System.out.println(j);
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user