Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.automode
.automode-bak
.automode-temp
.updatecheck
config.ini
multiconfig-*.ini
Expand Down
14 changes: 14 additions & 0 deletions configs/Intel.AutomaticTestMode.yCruncher.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ startValues = -150 # Set the voltage offset to -150mv
maxValue = 0 # Do not go above a voltage offset of 0mvv
incrementBy = 10 # Adjust the voltage offset by 10mv after an error

# A core needs to complete this many test runs in a row without an error before the voltage offset
# is considered good for it
# Note that for Intel there is only a single voltage offset for all of the cores, so an adjustment
# resets this counter for every core
passesToConfirmCoreValue = 3

# Cycle through all of the cores instead of staying on one core until it is confirmed
# As there is only one voltage offset for all of the cores, this lets all of them collect their test runs at
# the same value, instead of confirming the first cores at a value that a later core then adjusts again
repeatCoreUntilConfirmed = 0

# The test runs until every core has found a good value, the "maxIterations" setting is not used
# The found values are permanently stored in the "*_automode-results.txt" file in the logs directory

# Try to automatically resume after a crash / hard reboot
# For this to work properly, Auto Logon should be activated
# Otherwise the computer will just idle at the logon screen after a crash
Expand Down
24 changes: 22 additions & 2 deletions configs/Ryzen.AutomaticTestMode.Start.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
# It sets the Curve Optimizer values to the minimum value and will make it less aggressive
# step by step when an error or a crash occurs
#
# This took around 8 hours for my 5900X starting at -30 Curve Optimizer until 10 iterations had completed
# The test now runs until every core has found a good value (or until the maxValue has been reached
# for a core), so expect this to take many hours
# The found values are permanently stored in the "*_automode-results.txt" file in the logs directory
#
# Author: sp00n

Expand All @@ -13,7 +15,8 @@ stressTestProgram = YCRUNCHER
runtimePerCore = auto
coreTestOrder = Default
numberOfThreads = 1
maxIterations = 10

# Note: maxIterations is not used in the Automatic Test Mode


[yCruncher]
Expand All @@ -32,6 +35,23 @@ maxValue = 0 # Do not go above Curve Optimizer value of 0
incrementBy = 1 # Adjust the Curve Optimizer value by 1 after an error


# A core needs to complete this many test runs in a row without an error before its Curve Optimizer
# value is considered good and the core is not tested anymore
# Higher values give you more confidence, but the test will take proportionally longer
passesToConfirmCoreValue = 3


# Stay on a core until it has a final value, so that one core is finished after the other
# Set this to 0 to test each core once per iteration and cycle through the whole test order repeatedly instead
repeatCoreUntilConfirmed = 1


# If you already know the good value for some of the cores, you can enter them here
# These cores will then not be tested at all
# You can find a ready to use line at the end of the "*_automode-results.txt" file of a previous run
#knownGoodValues = 3:-25, 7:-18


# Set the Curve Optimizer value only for the currently tested core
# All other cores will be set to 0, to avoid any possible interference
setVoltageOnlyForTestedCore = 1
Expand Down
88 changes: 86 additions & 2 deletions configs/default.config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ assignBothVirtualCoresForSingleThread = 0
# The max number of iterations
# High values are basically unlimited (good for testing over night)
#
# Note: This setting is not used in the Automatic Test Mode. There the test runs until every core has found a
# good value or has reached the "maxValue" setting
#
# Default: 10000
maxIterations = 10000

Expand Down Expand Up @@ -226,6 +229,8 @@ lookForWheaErrors = 1
# The testing on the core will be stopped and continued on the next one
# However only if the APIC ID from the WHEA message matches the core that was currently tested, otherwise
# only a warning will be displayed
# Some WHEA entries don't contain an APIC ID at all (e.g. a corrected memory error). As the tested core cannot be
# ruled out for those, they are also treated as an error
#
# Default: 1
treatWheaWarningAsError = 1
Expand Down Expand Up @@ -572,11 +577,32 @@ enableAutomaticAdjustment = 0
startValues = CurrentValues


# Curve Optimizer / voltage offset values that you already know to be stable
# Cores listed here are treated as already finished: they will never be tested, not even after
# an automatic resume, and their value is included in the results and the final summary
# The format is <core>:<value>, separated by commas, spaces or the "|" character
# The enumeration of cores starts with 0
#
# You can find a ready to use line at the end of the "_automode-results.txt" file of a previous run
#
# Note: This setting takes precedence over "startValues" for the listed cores
# Note: If a core is also listed in coresToIgnore, the coresToIgnore setting wins
# Note: This setting only works for Ryzen processors (Curve Optimizer), as the Intel
# implementation can currently only set a single voltage offset for all cores
#
# Example: knownGoodValues = 3:-25, 7:-18
# Default: (empty)
knownGoodValues =


# The upper limit for the Curve Optimizer values / voltage offset
# If this limit has been reached, no further adjustments will be performed
# Instead the core will now simply throw an error and the regular "skipCoreOnError" setting will be obeyed
# This is either a Curve Optimizer value or a voltage offset value
#
# Note: A core that still throws an error once it has reached this value will not be tested again,
# regardless of the "skipCoreOnError" setting. It will be listed as "could not be stabilized"
# in the final summary
#
# IMPORTANT: Be sensible about this value, setting it too high into the positive could apply a too high
# voltage to your CPU and may damage it!
#
Expand All @@ -595,16 +621,74 @@ maxValue = 0
incrementBy = Default


# The number of test runs without an error a core needs to be considered "good"
# A core counts as finished once it has completed this many test runs in a row without an error at the same
# Curve Optimizer / voltage offset value. If an error occurs, the value is made less aggressive and the counter
# starts over for this core
# Higher values give you more confidence, but the test will take proportionally longer
#
# Note: In the Automatic Test Mode, the "maxIterations" setting from the [General] section is not used
# The test keeps running until every core has either found a good value or has reached the "maxValue" setting
#
# Default: 3
passesToConfirmCoreValue = 3


# Stay on a core until it has a final value, instead of continuing with the next core after each test run
# With this enabled, a core is tested over and over again until it has collected its "passesToConfirmCoreValue"
# error free test runs, or until it has reached the "maxValue" setting. Only then the next core in line is selected
# This finishes one core after the other, so you already have final values for the cores that have been tested if
# you abort the run early
# If you set this to 0, each core is tested once per iteration and the test order is cycled through repeatedly, which
# spreads the test runs for a core over a longer period of time
#
# Note: This does not change the order in which the cores are selected, see the "coreTestOrder" setting for that
# Note: For the behavior after an error, see the "repeatCoreOnError" setting below
# Note: For Intel up to 14th gen there is only one voltage offset for all of the cores. A core that is confirmed
# early therefore keeps the value it was confirmed with, even if a later core makes the shared value less
# aggressive. Setting this to 0 is the better choice there, as it lets all of the cores collect their test
# runs at the same value
#
# Default: 1
repeatCoreUntilConfirmed = 1


# Set only the currently tested core to the selected Curve Optimizer / voltage offset value
# All the other cores will be set to 0, resp. the determined maximum value if it's higher than 0
# All the other cores will be set to 0, resp. the value from "voltageValueForNotTestedCores",
# or the determined maximum value if it's higher than any of those
# This should prevent errors caused by other cores than the currently tested one, or at least diminish the chance for that
#
# Note: Currently this only has an effect for Ryzen processors, for Intel up to 14th gen there is only one voltage value
# Note: Cores for which a good value has already been found are also set to "voltageValueForNotTestedCores",
# unless you enable the "applyConfirmedValuesForNotTestedCores" setting below
#
# Default: 0
setVoltageOnlyForTestedCore = 0


# If setVoltageOnlyForTestedCore above is enabled, you can define which Curve Optimizer / voltage offset value you want the other,
# currently not tested cores to be set to
#
# Note: If the "current value" for a core is higher than what is entered here, e.g. derived from the "startValues" setting or
# from errors during testing that caused an automatic adjustment, the higher value for this core will take priority over this setting
# to avoid instabilities
#
# Default: 0
voltageValueForNotTestedCores = 0


# Apply the already found good values to the cores that are not currently being tested
# This setting only has an effect if "setVoltageOnlyForTestedCore" is enabled
# By default all cores that are not currently being tested are set to "voltageValueForNotTestedCores", so that a
# crash can only have been caused by the tested core
# If you enable this setting, cores that already have a confirmed value will use that value instead. This tests the
# combination of all of the found values, but if the computer now crashes, it may have been caused by one of those
# other cores, and the result for the currently tested core may be wrong
#
# Default: 0
applyConfirmedValuesForNotTestedCores = 0


# Repeat the test on a core if it has thrown an error and the Curve Optimizer / voltage offset value was increased
# Setting this to 1 will restart the test, until it has not thrown an error, or until the maximum value has been reached
# Setting it to 0, the script will continue to the next core in line as normal
Expand Down
91 changes: 64 additions & 27 deletions helpers/automode-startup-script.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ $taskPath = '\CoreCycler\'
# This file is in \helpers, our main script is one level above
$scriptRoot = Split-Path -Path $PSScriptRoot -Parent
$autoModeFile = $scriptRoot + '\.automode'
$autoModeFileBak = $scriptRoot + '\.automode-bak'
$maxTimeLimit = 12 * 60 * 60


Expand Down Expand Up @@ -219,58 +220,94 @@ try {



if (!(Test-Path -LiteralPath $autoModeFile -PathType Leaf)) {
if (!(Test-Path -LiteralPath $autoModeFile -PathType Leaf) -and !(Test-Path -LiteralPath $autoModeFileBak -PathType Leaf)) {
Write-Text('The .automode file does not exist!')
Write-Text('The file is needed to be able to continue the testing process, aborting.')
Write-Text('(Looking for: ' + $autoModeFile + ')')
Write-Text('')

Remove-StartupTask

throw [EndTryBlockException] 'The .automode file does not exist, aborting!'
}



# Try to get the info from the .automode file
Write-Text('Parsing the .automode file:')
Write-Text($autoModeFile)
Write-Text('')
# There are two generations of the file, so if the current one is broken or missing, we can fall back to the previous one
$autoModeInfoFromJson = $null
$lastErrorMessage = 'Could not parse the .automode file!'

$reader = [System.IO.File]::OpenText($autoModeFile)
$autoModeFileContentString = $reader.ReadToEnd().Trim()
$reader.Close()
foreach ($thisFilePath in @($autoModeFile, $autoModeFileBak)) {
if (!(Test-Path -LiteralPath $thisFilePath -PathType Leaf)) {
continue
}

Write-Text('Parsing the .automode file:')
Write-Text($thisFilePath)
Write-Text('')

try {
$autoModeInfoFromJson = ConvertFrom-Json $autoModeFileContentString
}
catch {
throw [AutoModeResumeFailedException] ('Possible file corruption detected, could not parse the .automode file!' + [Environment]::NewLine + 'Reason: ' + $_.Exception.Message)
# Everything that can fail for this generation of the file needs to happen inside this try block,
# otherwise we would never get to the backup generation
# This includes reading the file itself (e.g. a sharing violation) and all of the casts of the stored values
try {
$autoModeFileContentString = [System.IO.File]::ReadAllText($thisFilePath).Trim()

$parsedJson = ConvertFrom-Json $autoModeFileContentString

# We have some required properties
@('fileTimestamp', 'lastCoreTested', 'logFileCoreCycler', 'logFileStressTest', 'voltageValues') | ForEach-Object {
if (!($parsedJson -and ($parsedJson | Get-Member $_))) {
throw ('The .automode file is missing the entry "' + $_ + '"!')
}
}

# There also needs to be a valid core that was being tested, otherwise we cannot resume anything
# CoreCycler would treat an invalid core number as a regular new run and start all over again
if ([Int] $parsedJson.lastCoreTested -lt 0) {
throw ('The .automode file doesn''t contain a valid tested core ("' + $parsedJson.lastCoreTested + '")!')
}

$fileTimestamp = [UInt64] $parsedJson.fileTimestamp
$lastCoreTested = [Int] $parsedJson.lastCoreTested
$logFileCoreCycler = [String] $parsedJson.logFileCoreCycler
$logFileStressTest = [String] $parsedJson.logFileStressTest
$voltageValues = [Array] $parsedJson.voltageValues
$waitBeforeResume = $(if ($parsedJson | Get-Member 'waitBeforeResume') { [Int] $parsedJson.waitBeforeResume } else { 0 }) # Optional

# Optional entries of the newer file format
$schemaVersion = $(if ($parsedJson | Get-Member 'schemaVersion') { [Int] $parsedJson.schemaVersion } else { 1 })
$storedIteration = $(if ($parsedJson | Get-Member 'iteration') { [Int] $parsedJson.iteration } else { 0 })
$remainingCores = $(if ($parsedJson | Get-Member 'remainingCoreOrder') { @([Array] $parsedJson.remainingCoreOrder) } else { @() })

$autoModeInfoFromJson = $parsedJson
break
}
catch {
$lastErrorMessage = $_.Exception.Message
Write-Text('Could not use this file: ' + $lastErrorMessage)
Write-Text('')
}
}


# We have some required properties
@('fileTimestamp', 'lastCoreTested', 'logFileCoreCycler', 'logFileStressTest', 'voltageValues') | ForEach-Object {
if (!($autoModeInfoFromJson -and ($autoModeInfoFromJson | Get-Member $_))) {
throw [AutoModeResumeFailedException] ('The .automode file is missing the entry "' + $_ + '"!')
}
if (!$autoModeInfoFromJson) {
throw [AutoModeResumeFailedException] ('Possible file corruption detected, could not parse the .automode file!' + [Environment]::NewLine + 'Reason: ' + $lastErrorMessage)
}


$fileTimestamp = [UInt64] $autoModeInfoFromJson.fileTimestamp
$lastCoreTested = [Int] $autoModeInfoFromJson.lastCoreTested
$logFileCoreCycler = [String] $autoModeInfoFromJson.logFileCoreCycler
$logFileStressTest = [String] $autoModeInfoFromJson.logFileStressTest
$voltageValues = [Array] $autoModeInfoFromJson.voltageValues
$waitBeforeResume = $(if ($autoModeInfoFromJson -and ($autoModeInfoFromJson | Get-Member 'waitBeforeResume')) { [Int] $autoModeInfoFromJson.waitBeforeResume } else { 0 }) # Optional

Write-Text('Timestamp: ' + $fileTimestamp)
Write-Text('Tested Core: ' + $lastCoreTested)
Write-Text('Logfile CoreCycler: ' + $logFileCoreCycler)
Write-Text('Logfile Stress Test: ' + $logFileStressTest)
Write-Text('Voltage Settings: ' + $voltageValues)
Write-Text('Wait before resume: ' + $waitBeforeResume)
Write-Text('File version: ' + $schemaVersion)

if ($schemaVersion -ge 2) {
Write-Text('Iteration: ' + $storedIteration)
Write-Text('Remaining cores: ' + $(if ($remainingCores.Count -gt 0) { $remainingCores -Join ', ' } else { '(none)' }))
}

Write-Text('')


Expand All @@ -296,7 +333,7 @@ try {

if ($fileTimestamp -lt $limitTimestamp) {
$actualTimeDiff = $curTimeStamp - $fileTimestamp
throw [AutoModeResumeFailedException] ('The resume timestamp is too long ago (too much time has passed: ' + [Math]::Round($actualTimeDiff / 60 / 60, 1) + ' hours, max: ' + [Math]::Round($limitTime / 60 / 60, 1) + ' hours)')
throw [AutoModeResumeFailedException] ('The resume timestamp is too long ago (too much time has passed: ' + [Math]::Round($actualTimeDiff / 60 / 60, 1) + ' hours, max: ' + [Math]::Round($maxTimeLimit / 60 / 60, 1) + ' hours)')
}


Expand Down
Loading