Skip to content

FX 支持使用 FP16#1049

Merged
Blinue merged 56 commits intodevfrom
feat/fp16
Feb 1, 2025
Merged

FX 支持使用 FP16#1049
Blinue merged 56 commits intodevfrom
feat/fp16

Conversation

@Blinue
Copy link
Owner

@Blinue Blinue commented Jan 2, 2025

效果可以使用 //!USE FP16 声明对半精度浮点数的支持,条件满足时会有以下变化:

  1. MP_FP16 被定义。
  2. MF 系列宏被定义为 min16float 族,如 MF4 为 min16float4,MF3x3为 min16float3x3 等。不使用 FP16 时这些宏被定义为对应的 float 类型。
  3. 符合条件的纹理被声明为 min16float 类型,例如 R16G16B16A16_FLOAT 格式的输入定义变为 Texture2D<min16float4>,输出定义变为 RWTexture2D<min16float4>;R16G16_UNORM 格式的输入定义变为 Texture2D<min16float2>,输出定义变为 RWTexture2D<unorm min16float2>。包含 32 位浮点数的格式仍使用 float 类型。

即使效果声明支持 FP16,也不意味着一定使用,有两种例外情况:GPU 不支持 FP16 或通过开发者选项禁用了 FP16。

添加了新的内置函数 MulAdd,等效于矩阵乘然后加上向量,让我们可以在 dp4 或 mad 之间灵活切换。目前大部分基于机器学习的效果大量使用 dp4,根据我的测试,切换为 mad 后性能提升相当可观。如果使用 FP16,mad 的性能可以进一步提升,而 dp4 的性能不升反降。

所有合适的效果都会适配 FP16 和 MulAdd,性能对比如下:

效果 当前 此 PR 使用 FP16 性能提升
Jinc 0.205ms 0.201ms +2%
Anime4K_3D_(AA_)Upscale_US 0.132ms 0.131ms +0.1%
Anime4K_Restore_(Soft_)S 0.161ms 0.154ms +4.3%
Anime4K_Restore_(Soft_)M 0.351ms 0.344ms +2%
Anime4K_Restore_(Soft_)L 0.559ms 0.433ms +22.5%
Anime4K_Restore_(Soft_)VL 1.22ms 0.862ms +29.3%
Anime4K_Restore_(Soft_)UL 2.82ms 1.83ms +35.1%
Anime4K_Upscale_(Denoise_)S 0.144ms 0.113ms +21.5%
Anime4K_Upscale_(Denoise_)L 0.549ms 0.432ms +21.3%
Anime4K_Upscale_(Denoise_)VL 1.38ms 1.08ms +21.7%
Anime4K_Upscale_(Denoise_)UL 2.44ms 1.92ms +21.3%
Anime4K_Upscale_GAN_x2_S 0.82ms 0.689ms +16%
Anime4K_Upscale_GAN_x2_M 1.73ms 1.31ms +24.3%
Anime4K_Upscale_GAN_x3_L 4.7ms 3.3ms +29.8%
CAS 0.016ms 0.015ms +6.3%
CuNNy-2x4C-NVL(-DN) 0.167ms 0.132ms +21%
CuNNy-3x4C-NVL(-DN) 0.213ms 0.166ms +22.1%
CuNNy-4x4C-NVL(-DN) 0.259ms 0.202ms +22%
CuNNy-8x4C-NVL(-DN) 0.443ms 0.336ms +24.2%
CuNNy-4x8C-NVL(-DN) 0.744ms 0.5ms +32.8%
CuNNy-6x8C-NVL(-DN) 1.19ms 0.702ms +41%
CuNNy-8x8C-NVL(-DN) 1.52ms 0.907ms +40.3%
CuNNy-4x16C-NVL(-DN) 4.8ms 1.8ms +62.5%
CuNNy-8x16C-NVL(-DN) 8.6ms 3.35ms +61%
CuNNy-16x16C-NVL(-DN) 15.7ms 6.4ms +59.2%
FSR_EASU 0.159ms 0.149ms +6.3%
FSR_RCAS 0.024ms 0.016ms +33.3%
FSR_EASU+FSR_RCAS 0.238ms 0.197ms +17.2%
FSRCNNX(_LineArt) 0.403ms 0.363ms +9.9%
ACNet 0.612ms 0.514ms +16%
NIS 0.181ms 0.173ms +4.4%
NVSharpen 0.027ms 0.027ms +0%

NIS 的性能提升是因为更新到了 v1.0.3,FP16 会使性能稍微下降,但显存占用更低。

其他更改:

  1. 添加开发者选项性能测试模式,开启后将持续渲染不做等待,用于测试效果的性能。
  2. 不再使用 wil::CreateDirectoryDeepNoThrow,因为它不支持相对路径,应改为使用 Win32Helper::CreateDir。
  3. 内联常量改为使用全局只读变量实现以避免宏定义引起的名字冲突,如 Fix effect shader compile error #678
  4. 引入 rapidhash,删除现有 wyhash 实现,这会使现有缓存失效,但也是清理技术债务的好机会。
  5. 优化效果缓存逻辑,避免出现哈希碰撞时读取错误的缓存,修改了缓存文件名。
  6. 效果可以在 //!MAGPIE EFFECT 块包含 StubDefs.hlsli 以减少 IDE 中的错误,不影响编译结果。

@Blinue
Copy link
Owner Author

Blinue commented Jan 3, 2025

我分别使用 N 卡(RTX 4070 Laptop)和 I 卡(Intel UHD)在同样的条件下测试结果如下:

效果 FP32-N FP16-N 性能提升 FP32-I FP16-I 性能提升
ACNet 0.64ms 0.56ms +12.5% 19.5ms 7.6ms +61%
Anime4K_Upscale_L 0.55ms 0.61ms -10.9% 53.9ms 63.3ms -17.4%
CuNNy-6x8C-NVL 0.93ms 1.1ms -18.3% 38.6ms 105ms -172%
Anime4K_Upscale_Denoise_UL 2.67ms 2.85ms -6.7% 490ms 421ms +14.1%
Anime4K_Restore_UL 2.95ms 2.81ms +4.7% 657ms 474ms +27.9%
Anime4K_Restore_Soft_UL 2.95ms 2.81ms +4.7% 657ms 470ms +28.5%
FSRCNNX 0.486ms 0.506ms -4.1% 14.6ms 6.2ms +57.5%

N 卡只有 ACNet 有较大的性能提升,其他效果反而下降;I 卡 ACNet 和 FSRCNNX 提升,其他则下降,而且性能变化幅度非常大。看来不同显卡的 FP16 性能差别很大,正确配置时可以大幅提高性能,反之则会大幅降低。这与我预想的不同,看来不能简单的全局启用或禁用。

@hooke007

This comment was marked as outdated.

@Blinue
Copy link
Owner Author

Blinue commented Jan 4, 2025

我这里串联了三个上了点强度,发现开关fp16的区别只能算误差...都是22.5xx ms波动

因为这几个效果还没做适配,现在都适配了。

@hooke007
Copy link
Collaborator

hooke007 commented Jan 4, 2025

好像还是不算明显

@Blinue
Copy link
Owner Author

Blinue commented Jan 4, 2025

试试 CuNNy-16x16C-NVL,我这里差别比较明显

FP16
image
FP32
image

@hooke007
Copy link
Collaborator

hooke007 commented Jan 4, 2025

。。。更慢了
fp16 -- fp32

@Blinue
Copy link
Owner Author

Blinue commented Jan 6, 2025

鉴于不同显卡 fp16 能力不同,我们应该支持针对单个效果启用或禁用 fp16。我想到两个方案:

  1. 允许用户针对单个效果启用 fp16
  2. 和 TensorRT 类似自动进行性能测试决定是否使用 fp16

我更喜欢第二个方案,虽然它很复杂,但优势很大

  1. 可以将粒度减小到通道,同一个效果内分别测试每个通道决定是否使用 fp16
  2. 不需要用户自己测试,开箱即用
  3. 为 TensorRT 铺路,由于机制类似,代码路径可以共用

@hooke007
Copy link
Collaborator

hooke007 commented Jan 6, 2025

我略作搜索好像确实只能算一点误差和显卡工作时频率影响的区别
image
nvidia的家用卡fp16和fp32似乎就是一个级别,这两代加入的fp16 tensor core和fp16不是一个东西
https://docs.nvidia.com/deeplearning/tensorrt/support-matrix/index.html#hardware-precision-matrix

These support matrices provide an overview of the supported platforms, features, and hardware capabilities of the TensorRT APIs, parsers, and layers.

@Blinue
Copy link
Owner Author

Blinue commented Jan 6, 2025

计算速度上 fp16 和 fp32 是一样的,fp16 的主要优势是驱动可以将 2 个 fp16 打包到一个 32 位 VGPR 寄存器。

  1. 如果驱动支持,一个指令可以同时计算两个 fp16 值,相当于时间减少了一半
  2. 使用的 VGPR 寄存器数量减少一半,VGPR 用的太多会影响并发性能

@plainround
Copy link

@soi8391 我也觉得老版本游戏更稳定
我打算就这个magpie性能问题向intel提交issue了,如果他们修不好,我就把5972用到换显卡🤪

@Blinue
Copy link
Owner Author

Blinue commented Jan 12, 2025

总结一下 @plainround 的测试结果

驱动版本 32.0.101.5972:

指令\精度 fp32 fp16
dp4 30.3ms
mad 55.6ms 12.4ms

驱动版本 32.0.101.6319:

指令\精度 fp32 fp16
dp4 49.9ms
mad 52.6ms 52.7ms

看来 6319 版本的 fp16 性能大幅下降了。

@Blinue
Copy link
Owner Author

Blinue commented Feb 1, 2025

这个功能完成了,感谢你们的测试!

鉴于不同显卡 fp16 能力不同,我们应该支持针对单个效果启用或禁用 fp16。我想到两个方案:

  1. 允许用户针对单个效果启用 fp16
  2. 和 TensorRT 类似自动进行性能测试决定是否使用 fp16

我更喜欢第二个方案,虽然它很复杂,但优势很大

  1. 可以将粒度减小到通道,同一个效果内分别测试每个通道决定是否使用 fp16
  2. 不需要用户自己测试,开箱即用
  3. 为 TensorRT 铺路,由于机制类似,代码路径可以共用

如果某些设备上 mad 比 dp4 更慢,这个功能还是有必要的,目前只发现 I 系独立显卡是这样,而且可能是驱动 bug。需要更多测试。

@Blinue Blinue merged commit a6f86d0 into dev Feb 1, 2025
2 checks passed
@Blinue Blinue deleted the feat/fp16 branch February 1, 2025 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants