修改 TensorFlow C API 的代码,使得固定的 saved_model.pb 文件名变为可设置的
我在 2021 年 5 月份发出了一个 SpleeterMsvcExe 开源项目,当时是支持 11kHz 和 16kHz 两种模型,年底的时候又添加了对 22kHz 模型的支持。这三种不同频率上限的模型, variables 目录中的文件是完全相同的,只有 saved_model.pb 不同。但 TensorFlow 源码中这个文件名在 constants.h 中被定义为了固定值:

  1. // SavedModel proto filename.
  2. constexpr char kSavedModelFilenamePb[] = "saved_model.pb";
  3.  
  4. // SavedModel text format proto filename.
  5. constexpr char kSavedModelFilenamePbTxt[] = "saved_model.pbtxt";

用于加载模型的 ReadMetaGraphDefFromSavedModel() API 函数会调用 reader.cc 中的 ReadSavedModel() 函数:

  1. Status ReadSavedModel(const string& export_dir, SavedModel* saved_model_proto) {
  2.   LOG(INFO) << "Reading SavedModel from: " << export_dir;
  3.  
  4.   const string saved_model_pb_path =
  5.       io::JoinPath(export_dir, kSavedModelFilenamePb);
  6.   if (Env::Default()->FileExists(saved_model_pb_path).ok()) {
  7.     return ReadBinaryProto(Env::Default(), saved_model_pb_path,
  8.                            saved_model_proto);
  9.   }
  10.   const string saved_model_pbtxt_path =
  11.       io::JoinPath(export_dir, kSavedModelFilenamePbTxt);
  12.   if (Env::Default()->FileExists(saved_model_pbtxt_path).ok()) {
  13.     return ReadTextProto(Env::Default(), saved_model_pbtxt_path,
  14.                          saved_model_proto);
  15.   }
  16.   return Status(error::Code::NOT_FOUND,
  17.                 "Could not find SavedModel .pb or .pbtxt at supplied export "
  18.                 "directory path: " +
  19.                     export_dir);
  20. }

可以看到完全没有考虑让这个文件名可以被指定,而且一直到现在最新的 v2.12.0 版本都是这样的。

我之前曾经考虑过从模型下手,试图把三种种不同频率上限的模型合并为一个。搜索过几次 tensorflow saved model merge 之类的关键词,也借助 ChatGPT 修改过 checkpoint 到 saved model 的转换脚本,最终都没成功。而且从把 saved_model.pb 转换为 .pbtext 格式的结果看,整个 protobuf 文件中和频率上限相关的参数非常多,而且看文件里这些参数所在位置,也没法合并。

之前一直想尽量用官方提供的二进制版本,是考虑到这对于杀毒软件比较友好,自己编译的会有全新的 hash 值,有误报的风险。但现在考虑到 SpleeterMsvcExe, 即将发出的 WPF 版 Spleeter GUI 以及 BeatShow Player 程序的易用性,还是打算对 TensorFlow 的源码进行修改,自行编译一个版本来用了。

只是这一点需求,代码还是很好改的。直接在 ReadSavedModel() 中添加一段识别和处理环境变量的代码就可以了:

  1. Status ReadSavedModel(const string& export_dir, SavedModel* saved_model_proto) {
  2.   LOG(INFO) << "Reading SavedModel from: " << export_dir;
  3.  
  4.   const char* tf_alt_saved_model_pb = getenv("TF_ALT_SAVED_MODEL_PB");
  5.   if (tf_alt_saved_model_pb != nullptr) {
  6.     LOG(INFO) << "Environment variable TF_ALT_SAVED_MODEL_PB is set: " << tf_alt_saved_model_pb;
  7.     const string alt_saved_model_pb_path =
  8.         io::JoinPath(export_dir, tf_alt_saved_model_pb);
  9.     if (Env::Default()->FileExists(alt_saved_model_pb_path).ok()) {
  10.       LOG(INFO) << "Will use " << tf_alt_saved_model_pb << " instead of saved_model.pb";
  11.       return ReadBinaryProto(Env::Default(), alt_saved_model_pb_path,
  12.                              saved_model_proto);
  13.     } else {
  14.       return Status(error::Code::NOT_FOUND,
  15.                     "Could not find the specified .pb file: " + alt_saved_model_pb_path);
  16.     }
  17.   }
  18.  
  19.   const string saved_model_pb_path =
  20.       io::JoinPath(export_dir, kSavedModelFilenamePb);

不用改 API 接口的定义,兼容性和灵活性都比较好。程序中调用 TensorFlow C API 前,设置一下 TF_ALT_SAVED_MODEL_PB 环境变量的值就可以了。

对于 TensorFlow 的编译过程,可以参考上一篇文章:
TensorFlow C API 动态库 v1.15 版本的编译过程

2023-04-22 添加:

修改过的项目已经发到了 GitHub 上了: https://github.com/wudicgi/tensorflow-mod

实际的修改和之前贴的有差异,具体修改可以看 c5cfda2 这个提交。也可以直接下载 release 版本使用: https://github.com/wudicgi/tensorflow-mod/releases/tag/v1.15.5-mod.1
当前语言: 中文 (简体)
TensorFlow C API 动态库 v1.15 版本的编译过程

整个编译工程基本参照官方的 在 Windows 环境中从源代码构建 说明就可以完成。之前搜到一些更早的版本是用 Cmake + Visual Studio 编译的,貌似编译过程中容易产生一些问题。TensorFlow v1 的最后一个版本 1.15.5 是是用 Bazel 进行构建的,它会直接调用 MSVC 编译器,整个编译过程还是比较顺利的。

经过测试的构建配置一节中, tensorflow-1.15.0 编译时使用的 Python 版本为 3.5-3.7, 编译器为 MSVC 2017, 构建工具为 Bazel 0.26.1. 下面会使用这些推荐的版本。

1. 安装 Python 和 TensorFlow 软件包依赖项

我的电脑上已安装有 Python 3.7 和 3.9, 但是 PATH 中 3.9 的目录在前边,因此先调整顺序将 3.7 放到前边。不调整的话,调用 Python 前通过以下命令临时设置一下环境变量也可以:

set PATH=C:\Python\Python37-64\Scripts;C:\Python\Python37-64;%PATH%

因为 v1.15.5 版本的 /tensorflow/tools/pip_package/setup.py 文件里有 'keras_applications >= 1.0.8', 因此我将官方构建说明中 keras_applications 的安装版本由 1.0.6 改为了 1.0.8, 执行:

pip3 install six numpy wheel
pip3 install keras_applications==1.0.8 --no-deps
pip3 install keras_preprocessing==1.0.5 --no-deps

2. 安装 Bazel

我电脑上没有 Bazelisk, 也没有 Chocolatey 和 Scoop, 因此我选择手动安装 Bazel.

https://github.com/bazelbuild/bazel/releases/tag/0.26.1 下载 bazel-0.26.1-windows-x86_64.zip, 把它解压到任意一个目录,并且把这个目录加入到 PATH 中后, Bazel 就可以使用了。

首次运行 bazel.exe 时,它会解压一些文件到 C:\Users\%USERNAME% 目录下,之后编译时生成的一些中间文件也会在用户的 Profile 目录下。

3. 安装 MSYS2

MSYS2 的安装可以参考 https://www.msys2.org/ 首页的说明。我的电脑上已经安装有 MSYS2 了,就只执行了一下 pacman:

pacman -S git patch unzip

并且确保 C:\msys64\usr\bin 在 PATH 中。

4. 安装 Visual Studio

我的电脑已安装有 Visual Studio 2017 和 2022.

如果没有安装任何版本的 Visual Studio, 要安装 VS 2017 可以到 https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/ 下载,可能需要登录 Microsoft 账号。

如果已经安装有 VS 2019, 2022 等更高版本,建议先尝试是否能正常编译。在已安装高版本 VS 的情况下安装低版本 VS 可能会有问题。

5. 下载 TensorFlow 源代码

使用 TortoiseGit 克隆版本库 https://github.com/tensorflow/tensorflow.git, 分支填写 v1.15.5, 深度填写 1.

6. 配置 build

在克隆得到的 tensorflow 目录中,执行:

python ./configure.py

如果不需要 GPU 支持,可以所有问题都选择默认值。

7. 构建 C API 库文件

执行以下命令构建 C API 的 dll 和 lib 文件:

bazel build --config=v1 --config=opt //tensorflow:tensorflow.dll
bazel build --config=v1 --config=opt //tensorflow:tensorflow.lib

在我的 5900X 上整个编译过程耗时约 14 分钟,生成文件大小和官方提供的 libtensorflow-cpu-windows-x86_64-1.15.0.zip 基本相同。

2023-04-22 添加:

编译时可以使用命令:

bazel build --config=v1 --copt=/arch:AVX --copt=/arch:AVX2 tensorflow:tensorflow.dll tensorflow:tensorflow_dll_import_lib

这样可以忽略掉为 opt config 配置的编译参数,直接指定编译支持 AVX 和 AVX2 的版本 (执行 python ./configure.py 时, opt config 的编译参数默认只有 /arch:AVX, 会缺少对 AVX2 的支持)。
当前语言: 中文 (简体)
入手 RTX 4070 显卡
去年夏天装的 AMD 5900X 的电脑,因为显卡价格原因没有买新显卡,而是接着用 2016 年买的 1050ti 显卡。6 年前的显卡显然已经非常不够用了,除了运算速度慢, 4GB 显存有些现在流行的开源项目根本跑不了。

前两天看到 4070 显卡发售了,查了下非常适合我用。华硕有一个双风扇的 DUAL GeForce RTX4070-12G 显卡,长度 27cm, 不用换机箱了。最大功耗 200W, 现在用的 750W 的电源也不用换了。为了保险又等了两天,稍微查了下 40 系另外 3 个型号的区别,在不需要 4090 算力的情况下, 4080 和 4090 比毫无性价比, 4070ti 比 4070 又强得有限,基本不用犹豫了。

今天上午下单,下午收到显卡。装上后简单测了下性能提升,和新的超分辨率功能。

性能提升

Whisper 的 ggml-large.bin 模型试了一下,之前用 1050ti 对一个 06:24 (384 秒) 的音频文件进行处理,耗时 160 秒:

Using GPU "NVIDIA GeForce GTX 1050 Ti", feature level 12.1, effective flags Wave32 | NoReshapedMatMul
Loaded MEL filters, 62.8 kb RAM
Loaded vocabulary, 51865 strings, 3037.1 kb RAM
Loaded 1259 GPU tensors, 2950.66 MB VRAM
Loaded model from "E:\Softwares\whisper-bin-x64\models\ggml-large.bin" to VRAM
Created source reader from the file "E:\CloudMusic\Nikita Fomin\Stranger (Dream Version).mp3"
[00:00:00.000 --> 00:00:03.480]   [MUSIC PLAYING]
...
[00:06:20.600 --> 00:06:23.600]   [MUSIC PLAYING]
    CPU Tasks
LoadModel       2.77043 seconds
RunComplete     161.1 seconds
Run     160.168 seconds
...
    GPU Tasks
LoadModel       2.10459 seconds
Run     160.019 seconds
...

换成 4070 显卡后,耗时 26 秒:

Using GPU "NVIDIA GeForce RTX 4070", feature level 12.1, effective flags Wave32 | NoReshapedMatMul
Loaded MEL filters, 62.8 kb RAM
Loaded vocabulary, 51865 strings, 3037.1 kb RAM
Loaded 1259 GPU tensors, 2950.66 MB VRAM
Computed CPU base frequency: 3.69996 GHz
Loaded model from "E:\Softwares\whisper-bin-x64\models\ggml-large.bin" to VRAM
Press Control+C or Control+Break to close this window
Created source reader from the file "E:\CloudMusic\Nikita Fomin\Stranger (Dream Version).mp3"
[00:00:00.000 --> 00:00:03.480]   [MUSIC PLAYING]
...
[00:06:20.600 --> 00:06:23.600]   [MUSIC PLAYING]
    CPU Tasks
LoadModel       1.56206 seconds
RunComplete     27.2146 seconds
Run     26.2726 seconds
...
    GPU Tasks
LoadModel       917.515 milliseconds
Run     26.1418 seconds
...

仅就这个应用来说,处理速度是之前的 6.15 倍。

超分辨率 (RTX Video Super Resolution) 功能

https://downloads.videolan.org/testing/vlc-rtx-upscaler/

https://github.com/emoose/VideoRenderer/releases/tag/rtx-1.1

https://www.videohelp.com/software/MPC-BE

K-Lite Mega Codec Pack 17.0.0, 2022-6-8

MPC-HC (Nightly, 64-bit)
------------------------

Build information:
    Version:            1.9.21.24 (1c7cdd24a)
    Compiler:           MSVC v19.29.30143
    Build date:         May 12 2022

LAV Filters:
    LAV Splitter:       0.76.1.3
    LAV Video:          0.76.1.3
    LAV Audio:          0.76.1.3
    FFmpeg compiler:    MinGW-w64 GCC 10.2.0

Operating system:
    Name:               Windows 10 (Build 21H2)
    Version:            10.0.19045 (64-bit)

Hardware:
    CPU:                AMD Ryzen 9 5900X 12-Core Processor
    GPU:                NVIDIA GeForce RTX 4070 (driver version: 31.0.15.3161)
当前语言: 中文 (简体)
更多条目: [1]
« 上一页 · 下一页 »