本文介绍如何在使用 Windows 机器学习时管理应用程序的性能。
线程处理和并发
从运行时公开的每个对象都是 敏捷的,这意味着可以从任何线程访问它们。 有关 敏捷的详细信息,请参阅 C++/WinRT 中的敏捷对象 。
将使用的一个关键对象是 LearningModelSession。 从任何线程调用此对象始终是安全的。
对于 GPU 会话:对象将锁定和同步并发调用。 如果需要并发,则需要创建多个会话才能实现它。
对于 CPU 会话:对象不会锁定,并且将允许对单个会话进行并发调用。 必须注意管理自己的状态、缓冲区和绑定对象。
应注意并度量方案目标。 新式 GPU 体系结构的工作方式与 CPU 不同。 例如,如果低延迟是目标,则可能需要使用管道处理(而不是并发)来管理跨 CPU 和 GPU 引擎的运行方式。 有关多引擎同步的文章 是入门的绝佳位置。 如果吞吐量是目标(如一次处理尽可能多的图像),则通常希望使用多个线程和并发来使 CPU 饱和。
当涉及到线程处理和并发时,需要运行试验并测量计时。 你的性能将因目标和方案而显著变化。
内存利用率
LearningModel 和 LearningModelSession 的每个实例在内存中都有模型的副本。 如果使用的是小型模型,你可能并不担心,但如果使用的是非常大的模型,这就变得很重要。
若要释放内存,请对模型或会话调用 Dispose 。 不要直接删除它们,因为某些语言会执行延迟垃圾回收。
LearningModel 将副本保留在内存中,以启用新的会话创建。 释放 LearningModel 时,所有现有会话会继续运行。 但是,将无法再使用该 LearningModel 实例创建新会话。 对于大型模型,您可以创建一个模型和会话,然后销毁该模型。 通过使用单个会话来 评估所有调用,你将在内存中拥有大型模型的单个副本。
Float16 支持
为了提高性能和减少模型占用空间,可以使用 ONNXMLTools 将模型转换为 float16。
转换后,所有权重和输入均为 float16。 下面介绍如何使用 float16 输入和输出:
-
- 建议的用法。
- 将颜色转换并张量化为 float16。
- 支持 bgr8 和 8 位图像格式,这些格式可以安全地转换为 float16,而不会丢失数据。
-
- 高级路径。
- 将 float32 强制转换为 float16。
- 如果是图像,则可以安全地进行强制转换,因为 bgr8 较小并且适合。
- 如果不是图像,则 Bind 会失败,需改为传入 TensorFloat16Bit。
-
- 高级路径。
- 需要转换为 float16,并将输入作为 float32 传递,后者会被强制转换为 float16。
注释
大多数情况下,运算符仍在执行 32 位数学运算。 溢出的风险较小,结果将截断为 float16。 但是,如果硬件声明支持 float16,则运行时将利用它。
预处理输入数据
WinML 在幕后执行一些预处理步骤,使处理输入数据更简单、更高效。 例如,给定的输入图像可能采用各种颜色格式和形状,可能与模型预期不同。 WinML 对图像执行转换以匹配它们,从而减少开发人员的负载。
WinML 还利用整个硬件堆栈(CPU、GPU 等)为特定设备和方案提供最有效的转换。
但在某些情况下,可能需要手动将输入数据张量化,因为你有一些特定的要求。 例如,你可能不想对图像使用 VideoFrame ,或者想要将像素值从 0-255 规范化到范围 0-1。 在这些情况下,可以对数据执行你自己的自定义张量化操作。 如需此方面的示例,请参阅 Custom Tensorization Sample(自定义张量化示例)。
注释
使用以下资源获取有关 Windows ML 的帮助:
- 若要提出或回答有关 Windows ML 的技术问题,请在 Stack Overflow 上使用 windows-machine-learning 标记。
- 若要报告 bug,请在 GitHub 上提交问题。