|
|
@@ -11,7 +11,6 @@ const DEFAULT_MIN_TDP_PERCENT = 10;
|
|
|
const DEFAULT_MAX_TDP_PERCENT = 100;
|
|
|
const DEFAULT_TDP_STEP_PERCENT = 10;
|
|
|
const DEFAULT_CHECK_INTERVAL_MS = 2000;
|
|
|
-const DEFAULT_CMD_TIMEOUT_MS = 5000;
|
|
|
const DEFAULT_UPP_PATH = 'upp';
|
|
|
|
|
|
function loadConfig(configPath) {
|
|
|
@@ -30,7 +29,6 @@ function mergeConfig(config) {
|
|
|
maxTdpPercent: config.maxTdpPercent ?? DEFAULT_MAX_TDP_PERCENT,
|
|
|
tdpStepPercent: config.tdpStepPercent ?? DEFAULT_TDP_STEP_PERCENT,
|
|
|
checkIntervalMs: config.checkIntervalMs ?? DEFAULT_CHECK_INTERVAL_MS,
|
|
|
- cmdTimeoutMs: config.cmdTimeoutMs ?? DEFAULT_CMD_TIMEOUT_MS,
|
|
|
uppPath: config.uppPath ?? DEFAULT_UPP_PATH,
|
|
|
};
|
|
|
}
|
|
|
@@ -143,7 +141,20 @@ function setTdpForCard(cardNumber, power, config) {
|
|
|
`BoostPowerLimit=${power} ` +
|
|
|
`smcPPTable/SocketPowerLimitAc0=${power} ` +
|
|
|
`smcPPTable/SocketPowerLimitDc=${power}`;
|
|
|
- execSync(cmd, { encoding: 'utf-8', stdio: 'pipe', timeout: config.cmdTimeoutMs });
|
|
|
+ execSync(cmd, { encoding: 'utf-8', stdio: 'pipe' });
|
|
|
+}
|
|
|
+
|
|
|
+function getMaxTdp(cardNumber, config) {
|
|
|
+ try {
|
|
|
+ const cardPath = getCardPath(cardNumber);
|
|
|
+ const out = execSync(
|
|
|
+ `${config.uppPath} -p ${cardPath} get SmallPowerLimit1`,
|
|
|
+ { encoding: 'utf-8', stdio: 'pipe' }
|
|
|
+ ).trim();
|
|
|
+ const match = out.match(/(\d+(?:\.\d+)?)/);
|
|
|
+ if (match) return parseFloat(match[1]);
|
|
|
+ } catch { /* ignore */ }
|
|
|
+ return 120;
|
|
|
}
|
|
|
|
|
|
function parseArgs(argv) {
|
|
|
@@ -208,9 +219,14 @@ async function main() {
|
|
|
const gpuStates = cardIndices.map(cardNumber => ({
|
|
|
cardNumber,
|
|
|
deviceName: getDeviceName(cardNumber),
|
|
|
+ maxTdp: getMaxTdp(cardNumber, config),
|
|
|
currentTdpPercent: null,
|
|
|
}));
|
|
|
|
|
|
+ for (const state of gpuStates) {
|
|
|
+ log(`GPU ${state.cardNumber} [${state.deviceName}]: max TDP ${state.maxTdp}W`);
|
|
|
+ }
|
|
|
+
|
|
|
if (gpuStates.length === 0) {
|
|
|
log('No GPUs found');
|
|
|
process.exit(1);
|
|
|
@@ -259,12 +275,12 @@ async function main() {
|
|
|
|
|
|
if (shouldApply) {
|
|
|
const clampedPercent = Math.max(config.minTdpPercent, Math.min(config.maxTdpPercent, gpuState.currentTdpPercent));
|
|
|
- const power = wattsFromPercent(clampedPercent, 250);
|
|
|
+ const power = wattsFromPercent(clampedPercent, gpuState.maxTdp);
|
|
|
setTdpForCard(gpuState.cardNumber, power, config);
|
|
|
log(`GPU ${gpuState.cardNumber} [${gpuState.deviceName}]: ${temp.toFixed(1)}°C | TDP: ${clampedPercent}% (${power}W)`);
|
|
|
}
|
|
|
} else if (gpuState.currentTdpPercent !== null && iteration % 10 === 0) {
|
|
|
- const currentWatts = wattsFromPercent(gpuState.currentTdpPercent, 250);
|
|
|
+ const currentWatts = wattsFromPercent(gpuState.currentTdpPercent, gpuState.maxTdp);
|
|
|
log(`GPU ${gpuState.cardNumber} [${gpuState.deviceName}]: ${temp.toFixed(1)}°C | TDP: ${gpuState.currentTdpPercent}% (${currentWatts}W) (stable)`);
|
|
|
}
|
|
|
} catch (err) {
|