ManualVRAMTuning

Demonstrates how to control GPU manual VRAM tuning when programming with ADLX.

Command Prompts

Command Prompt Description
1 Get Memory Timing support.
2 Get Memory Timing level and VRAMTuning state(Frequency and Voltage).Enable
3 Set Memory Timing level.
4 Set VRAMTuning state.
M/m Show this menu.
Q/q Quit.

Sample Path

/Samples/CPP/GPUTuning/ManualVRAMTuning

Code

Copied!

//
// Copyright (c) 2021 - 2023 Advanced Micro Devices, Inc. All rights reserved.
//
//-------------------------------------------------------------------------------------------------


#include "SDK/ADLXHelper/Windows/Cpp/ADLXHelper.h"
#include "SDK/Include/IGPUManualVRAMTuning.h"
#include "SDK/Include/IGPUTuning.h"
#include <iostream>
#include <map>

// Use ADLX namespace
using namespace adlx;

// ADLXHelper instance
// No outstanding interfaces from ADLX must exist when ADLX is destroyed.
// Use global variables to ensure validity of the interface.
static ADLXHelper g_ADLXHelp;

// Display Memory Timing support
void ShowSupport(IADLXInterfacePtr& vramTuningIfc);

// Get VRAM state
void GetState(IADLXInterfacePtr& vramTuningIfc);

// Set Memory Timing Level
void SetTimingLevel(IADLXInterfacePtr& vramTuningIfc);

// Set VRAM state
void SetState(IADLXInterfacePtr& vramTuningIfc);

// Main menu
void MainMenu(IADLXInterfacePtr& vramTuningIfc);

// Menu action control
void MenuControl(IADLXInterfacePtr vramTuningIfc);

// Wait for exit with error message
int WaitAndExit(const char* msg, const int retCode);

int main()
{
    ADLX_RESULT  res = ADLX_FAIL ;

    // Initialize ADLX
    res = g_ADLXHelp.Initialize();

    if (ADLX_SUCCEEDED (res))
    {
        // Get GPUs
        IADLXGPUListPtr gpus;
        res = g_ADLXHelp.GetSystemServices()->GetGPUs(&gpus);
        if (ADLX_SUCCEEDED (res) && !gpus->Empty())
        {
            // Get GPU tuning service
            IADLXGPUTuningServicesPtr gpuTuningService;
            res = g_ADLXHelp.GetSystemServices()->GetGPUTuningServices(&gpuTuningService);
            if (ADLX_SUCCEEDED (res))
            {
                // Get GPU interface
                IADLXGPUPtr gpu;
                adlx_uint index = 0;
                res = gpus->At(index, &gpu);
                if (ADLX_SUCCEEDED (res))
                {
                    // Get manual VRAM tuning support
                    adlx_bool supported;
                    res = gpuTuningService->IsSupportedManualVRAMTuning(gpu, &supported);
                    if (ADLX_SUCCEEDED (res))
                        std::cout << "\tGPU manual VRAM tuning support status: " << supported << std::endl;
                    if (supported)
                    {
                        // Get manual VRAM tuning interface
                        IADLXInterfacePtr vramTuningIfc;
                        res = gpuTuningService->GetManualVRAMTuning(gpu, &vramTuningIfc);
                        if (ADLX_SUCCEEDED (res))
                        {
                            MainMenu(vramTuningIfc);
                            MenuControl(vramTuningIfc);
                        }
                    }
                    else
                    {
                        return WaitAndExit("\nThis GPU Doesn't support Manual VRAM Tuning", 0);
                    }
                }
            }
            else
                std::cout << "Failed to get GPU tuning services" << std::endl;
        }
        else
            std::cout << "Failed to get GPU" << std::endl;
    }
    else
        return WaitAndExit("\tg_ADLXHelp initialize failed", 0);

    // Destroy ADLX
    res = g_ADLXHelp.Terminate();
    std::cout << "Destroy ADLX res: " << res << std::endl;

    // Pause to see the print out
    system("pause");

    return 0;
}

static std::map<ADLX_MEMORYTIMING_DESCRIPTION, const char*> descMap =
    {
        {MEMORYTIMING_DEFAULT , "Default"},
        {MEMORYTIMING_FAST_TIMING , "Fast Timing"},
        {MEMORYTIMING_FAST_TIMING_LEVEL_2 , "Fast Timing Level2"},
        {MEMORYTIMING_AUTOMATIC , "Automatic"},
        {MEMORYTIMING_MEMORYTIMING_LEVEL_1 , "Memory Timing Level1"},
        {MEMORYTIMING_MEMORYTIMING_LEVEL_2 , "Memory Timing Level2"}};

void ShowSupport(IADLXInterfacePtr& vramTuningIfc)
{
    adlx_bool supported = false;
    IADLXManualVRAMTuning2Ptr vramTuning2(vramTuningIfc);
    IADLXManualVRAMTuning1Ptr vramTuning1(vramTuningIfc);
    ADLX_RESULT  res = ADLX_FAIL ;
    if (vramTuning2)
    {
        res = vramTuning2->IsSupportedMemoryTiming(&supported);
    }
    else if (vramTuning1)
    {
        res = vramTuning1->IsSupportedMemoryTiming(&supported);
    }
    std::cout << "\tIsSupported: " << supported << ", return code is: "<< res << "(0 means success)" << std::endl;
}

void GetState(IADLXInterfacePtr& vramTuningIfc)
{
    IADLXManualVRAMTuning2Ptr vramTuning2(vramTuningIfc);
    IADLXManualVRAMTuning1Ptr vramTuning1(vramTuningIfc);
    ADLX_MEMORYTIMING_DESCRIPTION  desc;
    IADLXMemoryTimingDescriptionListPtr descList;
    if (vramTuning2)
    {
        vramTuning2->GetSupportedMemoryTimingDescriptionList(&descList);
        vramTuning2->GetMemoryTimingDescription(&desc);

        adlx_int freq;
        ADLX_IntRange  rang;
        ADLX_RESULT  res = vramTuning2->GetMaxVRAMFrequency(&freq);
        std::cout << "\tMax VRAM frequency: " << freq << ", return code is: "<< res << "(0 means success)" << std::endl;
        res = vramTuning2->GetMaxVRAMFrequencyRange(&rang);
        std::cout << "\tMax VRAM frequency range: [" << rang.minValue  << " , " << rang.maxValue  << " ], step: " << rang.step
                  << ", return code is: "<< res << "(0 means success)" << std::endl;
    }
    else if (vramTuning1)
    {
        vramTuning1->GetSupportedMemoryTimingDescriptionList(&descList);
        vramTuning1->GetMemoryTimingDescription(&desc);

        IADLXManualTuningStateListPtr states;
        vramTuning1->GetVRAMTuningStates(&states);
        adlx_uint s = states->Begin();
        std::cout << "\tState is:" << std::endl;
        for (; s != states->End(); s++)
        {
            IADLXManualTuningStatePtr state;
            adlx_int frequency;
            adlx_int voltage;
            states->At(s, &state);
            state->GetFrequency(&frequency);
            state->GetVoltage(&voltage);
            std::cout << "\t\tfrequency: " << frequency << " voltage: " << voltage << std::endl;
        }

        ADLX_IntRange  frequencyRange;
        ADLX_IntRange  voltageRange;
        ADLX_RESULT  res = vramTuning1->GetVRAMTuningRanges(&frequencyRange, &voltageRange);
        std::cout << "\tFrequency range: [" << frequencyRange.minValue  << " , " << frequencyRange.maxValue  << " ], step: " << frequencyRange.step
                  << ", return code is: "<< res << "(0 means success)" << std::endl;
        std::cout << "\tVoltage range: [" << voltageRange.minValue  << " , " << voltageRange.maxValue  << " ], step: " << voltageRange.step
                  << ", return code is: "<< res << "(0 means success)" << std::endl;
    }
    if (descList)
    {
        std::cout << "\tCurrent timing desc: " << descMap[desc] << std::endl;
        std::cout << "\tSupported Memory Timing desc list:" << std::endl;
        for (adlx_uint s = 0; s != descList->End (); s++)
        {
            IADLXMemoryTimingDescriptionPtr item;
            descList->At (s, &item);
            item->GetDescription (&desc);
            std::cout << "\t  " << descMap[desc] << std::endl;
        }
    }
    std::cout << std::endl;
}

void SetTimingLevel(IADLXInterfacePtr& vramTuningIfc)
{
    ADLX_RESULT  res;
    IADLXManualVRAMTuning2Ptr vramTuning2(vramTuningIfc);
    IADLXManualVRAMTuning1Ptr vramTuning1(vramTuningIfc);
    ADLX_MEMORYTIMING_DESCRIPTION  desc, currentDesc;
    IADLXMemoryTimingDescriptionListPtr descList;
    bool supported = false;
    if (vramTuning2)
    {
        //If MemoryTiming is supported, then only will get the MemoryTimingDescriptionList
        res = vramTuning2->IsSupportedMemoryTiming(&supported);
        if (supported)
        {
            vramTuning2->GetSupportedMemoryTimingDescriptionList(&descList);
            if (descList)
            {
                vramTuning2->GetMemoryTimingDescription(&currentDesc);
                for (adlx_uint s = 0; s != descList->End(); s++)
                {
                    IADLXMemoryTimingDescriptionPtr item;
                    descList->At(s, &item);
                    item->GetDescription(&desc);
                    if (currentDesc != desc)
                    {
                        res = vramTuning2->SetMemoryTimingDescription(desc);
                        std::cout << "\tSet Memory Timing description to " << descMap[desc] << ": return code is: " << res << " (0 means success)" << std::endl;
                        break;
                    }
                }
            }
            else
            {
                std::cout << "\tFailed to get the Supported Memory Timing Description List." << std::endl;
            }
        }
        else
        {
            std::cout << "\tMemory Timing Level not Supported, so cannot set Memory Timing Description List." << std::endl;
        }
    }
    else if (vramTuning1)
    {
        //If MemoryTiming is supported, then only will get the MemoryTimingDescriptionList
        res = vramTuning1->IsSupportedMemoryTiming(&supported);
        if (supported)
        {
            vramTuning1->GetSupportedMemoryTimingDescriptionList(&descList);
            if (descList)
            {
                vramTuning1->GetMemoryTimingDescription(&currentDesc);
                for (adlx_uint s = 0; s != descList->End(); s++)
                {
                    IADLXMemoryTimingDescriptionPtr item;
                    descList->At(s, &item);
                    item->GetDescription(&desc);
                    if (currentDesc != desc)
                    {
                        res = vramTuning1->SetMemoryTimingDescription(desc);
                        std::cout << "\tSet Memory Timing description to " << descMap[desc] << ": return code is: " << res << " (0 means success)" << std::endl;
                        break;
                    }
                }
            }
            else
            {
                std::cout << "\tFailed to get the Supported Memory Timing Description List." << std::endl;
            }
        }
        else
        {
            std::cout << "\tMemory Timing Level not Supported, so cannot set Memory Timing Description List." << std::endl;
        }
    }
}

void SetState(IADLXInterfacePtr& vramTuningIfc)
{
    ADLX_RESULT  res;
    IADLXManualVRAMTuning2Ptr vramTuning2(vramTuningIfc);
    IADLXManualVRAMTuning1Ptr vramTuning1(vramTuningIfc);
    bool supported = false;
    if (vramTuning2)
    {
        //If MemoryTiming is supported, then only will set the MemoryTimingState
        res = vramTuning2->IsSupportedMemoryTiming(&supported);
        if (supported)
        {
            adlx_int freq;
            ADLX_IntRange  rang;
            vramTuning2->GetMaxVRAMFrequency(&freq);
            vramTuning2->GetMaxVRAMFrequencyRange(&rang);
            if (freq != rang.minValue )
            {
                res = vramTuning2->SetMaxVRAMFrequency(rang.minValue );
                std::cout << "\tUse min Frequency to set, return code(0 is Success) is: " << res << std::endl;
            }
            else
            {
                res = vramTuning2->SetMaxVRAMFrequency(rang.minValue  + rang.step  * 2);
                std::cout << "\tUse max Frequency to set, return code(0 is Success) is: " << res << std::endl;
            }
        }
        else
        {
            std::cout << "\tTuning not Supported, so cannot change the State." << std::endl;
        }
    }
    else if (vramTuning1)
    {
        //If MemoryTiming is supported, then only will set the MemoryTimingState
        res = vramTuning1->IsSupportedMemoryTiming(&supported);
        if (supported)
        {
            ADLX_IntRange  frequencyRange;
            ADLX_IntRange  voltageRange;
            vramTuning1->GetVRAMTuningRanges(&frequencyRange, &voltageRange);
            IADLXManualTuningStateListPtr states;
            vramTuning1->GetVRAMTuningStates(&states);
            adlx_uint s = states->Size() - 1;
            for (; s != states->End(); s++)
            {
                IADLXManualTuningStatePtr state;
                adlx_int frequency;
                adlx_int voltage;
                states->At(s, &state);
                state->GetFrequency(&frequency);
                state->GetVoltage(&voltage);
                // Only change the last
                res = state->SetFrequency(frequencyRange.maxValue  - frequencyRange.step  * 10);
                res = state->SetVoltage(voltageRange.maxValue  - voltageRange.step  * 10);
                break;
            }
            res = vramTuning1->SetVRAMTuningStates(states);
            std::cout << "\tChange VRAM tuning states, return code(0 is Success) is: " << res << std::endl;
        }
        else
        {
            std::cout << "\tTuning not Supported, so cannot change the State." << std::endl;
        }
    }
}

void MainMenu(IADLXInterfacePtr& vramTuningIfc)
{
    // Acquire to ManualVRAMTuning1
    IADLXManualVRAMTuning1Ptr vramTuning1(vramTuningIfc);
    // Acquire to ManualVRAMTuning2
    IADLXManualVRAMTuning2Ptr vramTuning2(vramTuningIfc);

    std::cout << "\tChoose from the following options:" << std::endl;

    std::cout << "\t->Press 1 to display Memory Timing support" << std::endl;
    if (vramTuning2)
        std::cout << "\t->Press 2 to get Memory Timing level and frequency range" << std::endl;
    else if (vramTuning1)
        std::cout << "\t->Press 2 to get Memory Timing level, VRAM frequency, and the voltage global range for all states" << std::endl;

    std::cout << "\t->Press 3 to change current Memory Timing Level" << std::endl;

    if (vramTuning2)
        std::cout << "\t->Press 4 to change current VRAM max frequency value" << std::endl;
    else if (vramTuning1)
        std::cout << "\t->Press 4 to change VRAM states" << std::endl;

    std::cout << "\t->Press Q/q to terminate the application" << std::endl;
    std::cout << "\t->Press M/m to display main menu options" << std::endl;
}

void MenuControl(IADLXInterfacePtr vramTuningIfc)
{
    int num = 0;
    while ((num = getchar()) != 'q' && num != 'Q')
    {
        switch (num)
        {
        // Get Memory Timing support
        case '1':
            ShowSupport(vramTuningIfc);
            break;

        // Get VRAM state
        case '2':
            GetState(vramTuningIfc);
            break;

        // Set timing level
        case '3':
            SetTimingLevel(vramTuningIfc);
            break;

        // Set VRAM state
        case '4':
            SetState(vramTuningIfc);
            break;

        // Display menu options
        case 'm':
        case 'M':
            MainMenu(vramTuningIfc);
            break;
        default:
            break;
        }
    }
}

int WaitAndExit(const char* msg, const int retCode)
{
    // Printout the message and pause to see it before returning the desired code
    if (nullptr != msg)
        std::cout << msg << std::endl;

    system("pause");
    return retCode;
}