AMD Radeon Vega Frontier Edition 与 Windows Server 2016 的调整小记

最近入手了一块农企的显卡,Vega Frontier Edition。本来是一件令人兴奋的事情,但是在使用的过程中碰到了很多这样或者那样的问题,仅把一些问题以及其解决方案记录下来。

首先说明一下我的平台配置:
Windows 版本 – Windows Server 2016 Datacenter
系统内存 – 32 GB
CPU 类型 – Intel(R) Xeon(R) CPU E5-2678 v3 @ 2.50GHz

前两天在AMD官网上寻找驱动的时候,有两个版本的驱动,一个是17.12.2 版本的Adrenalin Edition,另一个是18.Q1版本的Enterprise Edition 但是经过测试,仅有17.12.2版本的驱动可以安装在我的平台上,(后来用其他平台测试证实,是由于操作系统的版本导致的在新版Win10上可以正常运行,初步怀疑是和系统内核版本有关系)邮件咨询AMD后回复是:

由于Vega Frontier Edition显卡不是服务器显卡,暂时没有提供Windows Server下的驱动,故当您安装驱动时显示无法正确安装。建议您使用提供驱动的Win7/10 64位系统。

所以以下测试均基于17.12.2版本驱动。(但事实上很多问题的解决方法并不局限于此版本)

首先第一个问题就出在其显卡驱动模式切换上。根据宣传,这张卡有专用的驱动可以支持游戏模式和专业模式的切换,以满足开发和游戏有共同需求的群体(还有有信仰的人群体)。但是在切换显卡的时候会出现驱动程序回滚的情况。比方说在从17.12.2专业版切换到17.12.2游戏版的时候,往往会在切换完成后自动回滚至17.7游戏版,导致很多新游戏无法体验。这个问题的原因尚不明确,主要还是系统兼容性问题,由于AMD显卡驱动会在出现问题的时候自动回滚,所以在切换显卡驱动模式的时候,总有很大概率出发一些未知的错误。

这里的解决方法是打开设备管理器,找到显卡的驱动,点击更新驱动,在浏览计算机上的驱动程序里边点从驱动程序列表中选取,双击重新安装即可解决。

第二个问题出在其显卡温度控制策略上。在游戏模式下,其温度策略和电源控制可以用WattMan来调整,非常方便。但是在专业模式下,其并没有提供这样的一个工具。但是其默认的温度控制策略并不尽人意,风扇转速最高2000转,然而即便达到2000转,也很难维持核心温度不高于95度,尤其是在使用ProRender进行渲染的时候,常常会因为过热保护而导致程序出错,十分闹心。

后来想来想去想通过修改显卡vBIOS的手段来改变其温度控制策略,进行了一些尝试,由于没有现成的Vega BIOS Editor这样的修改工具,所以选择使用UE进行编辑,屡次尝试刷入BIOS均失败。后来发现在Vega之后,显卡的BIOS都进行了签名或者之类的操作,导致用户无法自行编辑BIOS。(好在显卡有双BIOS,可以在尝试失败后恢复原来的BIOS)

后来在网上找到了一个解决方法,即修改注册表的方法,其原理是通过给注册表中添加PowerPlay表,来调整显卡的策略。虽然具体的原理不是很了解,但是根据我的推测,由于这个PowerPlay表可以在vBIOS中可以找到一模一样的一段数据,应该就是显卡的电源温度频率等一些参数的配置表格,vBIOS中有一默认的,而驱动修改后的则会储存在注册表中方便调用。

由于其在注册表中的结构和其在vBIOS中的结构一致,所以在解析其结构的时候可以参照Linux中对于AMD显卡的参数处理:GitHub-torvalds/linux

以下为我根据我的需求修改了之后的注册表文件以及原版注册表文件。设置了最高风扇转速为4000转,最低转速为1000转,并在显卡温度低于40摄氏度时关闭散热风扇,在温度高于45度时重新开启。转速自动调整并控制显卡温度不超过70摄氏度。

MorePowerVegaFE-default

MorePowerVegaFE-optimized

我修改的过程则参考国外的一篇帖子:Preliminary view of AMD VEGA Bios

这篇帖子以Vega 64/Vega 56为例,列举了一些参数的修改和超频方法,其主要目的在于Vega 64/Vega 56的超频测试,由于我只需要修改其中的温度控制部分,所以我参照了这个结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef struct _ATOM_Vega10_Fan_Table_V2 {
0B UCHAR ucRevId;
E4 12 (0x12E4 = 4836)     USHORT usFanOutputSensitivity;
AC 0D (0xDAC = 3500 RPM)  USHORT usFanAcousticLimitRpm;
AC 0D (0xDAC = 3500 RPM)  USHORT usThrottlingRPM;
46 00 (0x46 = 70°C)       USHORT usTargetTemperature;
23 00 (0x23 = 35)         USHORT usMinimumPWMLimit;
54 03 (0x354 = 852)       USHORT usTargetGfxClk;
90 01 (0x190 = 400)       USHORT usFanGainEdge;
90 01 (0x190 = 400)       USHORT usFanGainHotspot;
90 01 (0x190 = 400)       USHORT usFanGainLiquid;
90 01 (0x190 = 400)       USHORT usFanGainVrVddc;
90 01 (0x190 = 400)       USHORT usFanGainVrMvdd;
90 01 (0x190 = 400)       USHORT usFanGainPlx;
90 01 (0x190 = 400)       USHORT usFanGainHbm;
01 (01 = on / 00 = off)   UCHAR ucEnableZeroRPM;
28 00 (0x28 = 40°C)       USHORT usFanStopTemperature;
32 00 (0x32 = 50°C)       USHORT usFanStartTemperature;
02                        UCHAR ucFanParameters;
08 (800 RPM)              UCHAR ucFanMinRPM;
23 (0x23 = 35 = 3500 RPM) UCHAR ucFanMaxRPM;
} ATOM_Vega10_Fan_Table_V2;

而如果想要修改其频率和电源策略的话,如果仅是修改最高状态,进行跑分测试,则完全可以参考原贴中的修改方式,而如果想要自己设置频率曲线或者显存频率曲线,则需要自行参考代码进行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
typedef struct _ATOM_Vega10_POWERPLAYTABLE {
    typedef struct _ATOM_COMMON_TABLE_HEADER
    {
    B6 02 (0x2B6)  USHORT usStructureSize;
    08             UCHAR  ucTableFormatRevision;   /*Change it when the Parser is not backward compatible */
    01             UCHAR  ucTableContentRevision;  /*Change it only when the table needs to change but the firmware */
                                                   /*Image can't be updated, while Driver needs to carry the new table! */
    } ATOM_COMMON_TABLE_HEADER;
00                      UCHAR  ucTableRevision;
5C 00                   USHORT usTableSize;                        /* the size of header structure */
E1 06 00 00             ULONG  ulGoldenPPID;                       /* PPGen use only */
EE 2B 00 00             ULONG  ulGoldenRevision;                   /* PPGen use only */
1B 00                   USHORT usFormatID;                         /* PPGen use only */
48 00 00 00             ULONG  ulPlatformCaps;                     /* See ATOM_Vega10_CAPS_* */
80 A9 03 00 (2400MHz)   ULONG  ulMaxODEngineClock;                 /* For Overdrive. */
F0 49 02 00 (1500MHz)   ULONG  ulMaxODMemoryClock;                 /* For Overdrive. */
32 00                   USHORT usPowerControlLimit;
08 00                   USHORT usUlvVoltageOffset;                 /* in mv units */
00 00                   USHORT usUlvSmnclkDid;
00 00                   USHORT usUlvMp1clkDid;
00 00                   USHORT usUlvGfxclkBypass;
00 00                   USHORT usGfxclkSlewRate;
00                      UCHAR  ucGfxVoltageMode;
00                      UCHAR  ucSocVoltageMode;
00                      UCHAR  ucUclkVoltageMode;
00                      UCHAR  ucUvdVoltageMode;
00                      UCHAR  ucVceVoltageMode;
02                      UCHAR  ucMp0VoltageMode;
01                      UCHAR  ucDcefVoltageMode;
5C 00 (0x5C)            USHORT usStateArrayOffset;                 /* points to ATOM_Vega10_State_Array */
4F 02 (0x24F)           USHORT usFanTableOffset;                   /* points to ATOM_Vega10_Fan_Table */
46 02 (0x246)           USHORT usThermalControllerOffset;          /* points to ATOM_Vega10_Thermal_Controller */
94 00 (0x94)            USHORT usSocclkDependencyTableOffset;      /* points to ATOM_Vega10_SOCCLK_Dependency_Table */
9E 01 (0x19E)           USHORT usMclkDependencyTableOffset;        /* points to ATOM_Vega10_MCLK_Dependency_Table */
BE 00 (0xBE)            USHORT usGfxclkDependencyTableOffset;      /* points to ATOM_Vega10_GFXCLK_Dependency_Table */
28 01 (0x128)           USHORT usDcefclkDependencyTableOffset;     /* points to ATOM_Vega10_DCEFCLK_Dependency_Table */
7A 00 (0x7A)            USHORT usVddcLookupTableOffset;            /* points to ATOM_Vega10_Voltage_Lookup_Table */
8C 00 (0x8C)            USHORT usVddmemLookupTableOffset;          /* points to ATOM_Vega10_Voltage_Lookup_Table */
BC 01 (0x1BC)           USHORT usMMDependencyTableOffset;          /* points to ATOM_Vega10_MM_Dependency_Table */
00 00                   USHORT usVCEStateTableOffset;              /* points to ATOM_Vega10_VCE_State_Table */
00 00                   USHORT usReserve;                          /* No PPM Support for Vega10 */
72 02 (0x272)           USHORT usPowerTuneTableOffset;             /* points to ATOM_Vega10_PowerTune_Table */
00 00                   USHORT usHardLimitTableOffset;             /* points to ATOM_Vega10_Hard_Limit_Table */
90 00 (0x90)            USHORT usVddciLookupTableOffset;           /* points to ATOM_Vega10_Voltage_Lookup_Table */
A8 02 (0x2A8)           USHORT usPCIETableOffset;                  /* points to ATOM_Vega10_PCIE_Table */
6D 01 (0x16D)           USHORT usPixclkDependencyTableOffset;      /* points to ATOM_Vega10_PIXCLK_Dependency_Table */
43 01 (0x143)           USHORT usDispClkDependencyTableOffset;     /* points to ATOM_Vega10_DISPCLK_Dependency_Table */
97 01 (0x197)           USHORT usPhyClkDependencyTableOffset;      /* points to ATOM_Vega10_PHYCLK_Dependency_Table */
} ATOM_Vega10_POWERPLAYTABLE;

上面这个表格是PowerPlay的Header结构体,里面包含了很多其它表格的地址等,值得注意的是,如果将我提供的注册表中的文件中16进制的第一字节定义为0地址,则该表格中所有的Table的地址指针需要减去0x34.

所有表格的结构均可参考Linux驱动中的vega10_pptable.h文件将数据与结构体一一比对即可。

(完)