如何通过优化 Python 中的 GPU 使用率将视频处理速度提高 5 倍(教程含源码)

Posted 知识大胖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过优化 Python 中的 GPU 使用率将视频处理速度提高 5 倍(教程含源码)相关的知识,希望对你有一定的参考价值。

我们这些 ML 领域的人都熟悉采用很酷的算法并使其做好生产准备的困难。在 Lightricks 研究基础架构团队,我们的工作是推动 Lightricks 研究部门完成的开创性工作并使其运行得更快,以便我们的用户能够享受到最佳的用户体验。

我们的一些用例涉及处理视频,因此能够有效地解码和预处理它们成为一项重要任务。在这篇博文中,我将展示我们如何将视频的解码和预处理速度提高 5 倍,同时利用 GPU 惊人的并行处理能力,同时保持代码简单且易于维护。

我开始与一支优秀的研究人员团队合作,研究在云中处理的视频功能,并发现现有的加载和预处理视频的方式运行良好。代码接收到文件的路径,在循环中逐帧读取它,根据一些预定义的配置调整帧的大小,并返回下采样帧的列表。

它看起来像这样:

import imageio as io
 
VIDEO_PATH = "vid_10sec_3584x2240.mp4"
IMAGE_SIZE_LOW =(96, 192)
 
def preprocess_video(video_path, image_size_low):
   frames_low = []
   for image in io.imiter(video_path):
       # Resize in a few iterations using cv2
       image_low = resize_frame(image, image_size_low)
       frames_low.append(image_low)
 
   return frames_low
 
print("Preprocessing on CPU...")
s = time.time()
frames = preprocess_video(video_path=VIDEO_PATH, image_size_low=IMAGE_SIZE_LOW)

如何优化 VBO/IBO 以最大化 GPU 缓存使用率

【中文标题】如何优化 VBO/IBO 以最大化 GPU 缓存使用率【英文标题】:How to Optimizing a VBO/IBO to maximize GPU cache usage 【发布时间】:2015-09-22 21:54:18 【问题描述】:

我正在使用在 CUDA 上运行的 Marching Cubes 算法从体积数据生成网格。

我尝试过保存网格并以 3 种方式渲染它。

    将一组粗略的三角形保存为顶点数据的连续数组。 如果第一次通过,我估计大小,创建一个 OpenGL VBO, 将其映射到 CUDA 并按以下格式将顶点数据写入其中

V0x, V0y, V0z, N0x, N0y, N0z, V1x, V1y, V1z, N1x, N1y, N1z, ...

并使用glDrawArrays() 绘制它。

VBO 中的冗余顶点,每个立方体的冗余顶点,无索引。

    从步骤 1 中获取网格,使用 thrust::sort()thrust::unique() 删除冗余顶点,使用 thrust::lower_bound() 计算索引。将结果保存到映射到 CUDA 的 OpenGL VBO/IBO。 使用glDrawElements() 绘制模型。

VBO 中没有冗余顶点,生成索引。

    为每个立方体生成一个唯一的顶点列表,将它们连同在 IBO 中形成三角形的索引一起存储在 VBO 中。使用 glDrawElements() 渲染。

VBO 中的冗余顶点、每个立方体的唯一顶点、每个立方体生成的索引

现在我在相同 ISO-Value ` 下获得的相同数据集的 FPS 是

Method 1 : 92  FPS, 30,647,016 Verts,          0 Indices
Method 2 : 122 FPS,  6,578,066 Verts, 30,647,016 Indices
Method 3 : 140 FPS, 20,349,880 Verts, 30,647,016 Indices

即使方法 2 产生的顶点数量最少,FPS 也很低。我相信这是因为索引的顺序可以最大限度地减少 GPU 缓存的使用。方法 3 的索引顺序获得更高的 GPU 缓存使用率,因此 FPS 更高。

如何修改/修改方法 2 以产生更高的 FPS?

【问题讨论】:

你的 FPS 测量方法是否考虑到使用推力去除冗余顶点所需的时间? @m.s.删除只进行一次。我不是在寻找实时删除方法。当 iso 值发生变化时,我只是在方法 1 中渲染粗网格。一旦变化保持不变,我就会处理大约需要 4 秒的移除。之后我只使用 VBO/IBO 来渲染网格。我希望这个网格有更高的 FPS,而只是渲染,当我测量 FPS 时不进行提取或压缩。 【参考方案1】:

有两件事可以提供帮助:

尝试通过将顶点大致按照绘制它们的顺序来优化数据缓存的使用 正在尝试优化post transform cache 的使用(here 有一个算法可以做到这一点,网上可能可以找到实现)

【讨论】:

谢谢@Jerem,我会试试这个算法Fast Vertex Cache Opt。将更新结果如何。我想找到一些使用尽可能少内存的算法,因为我的网格尺寸往往会变得非常大。 尝试了上述算法的 CPU 实现,它可以工作,但速度太慢。 60K 网格需要超过 12 秒,我的网格超过 20M,对于这种尺寸的网格来说是不可行的。正在寻找一种可扩展到 GPU 的解决方案。 您是否尝试按照绘制顺序对顶点进行排序? 嗯,是的,我在排序数百万个顶点时遇到了其他问题。如果我在 GPU 上执行它并且在 CPU 上太慢,我会遇到内存限制。但是你的答案是正确的以获得最佳的缓存命中率,但是由于网格大小,我将它用于我的应用程序是不可行的。不过我会接受这个答案。谢谢。 答案包含死链接。

以上是关于如何通过优化 Python 中的 GPU 使用率将视频处理速度提高 5 倍(教程含源码)的主要内容,如果未能解决你的问题,请参考以下文章

GPU怎么优化?

如何使用 Python 和 Numba 获取 GPU 中的 CUDA 内核数量?

[Unity优化] Unity中的批处理优化与GPU Instancing

如何在 Python 中获取每秒的 GPU 使用率

美团视觉GPU推理服务部署架构优化实践

gpu版本低能用啥跑代码