0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用Warp在Python环境中编写CUDA内核

星星科技指导员 ? 来源:NVIDIA ? 作者:NVIDIA ? 2022-04-02 16:15 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

通常,实时物理模拟代码是用低级 CUDA C ++编写的,以获得最佳性能。在这篇文章中,我们将介绍 NVIDIA Warp ,这是一个新的 Python 框架,可以轻松地用 Python 编写可微图形和模拟 GPU 代码。 Warp 提供了编写高性能仿真代码所需的构建块,但它的工作效率与 Python 等解释语言相当。

在这篇文章的最后,您将学习如何使用 Warp 在 Python 环境中编写 CUDA 内核,并利用一些内置的高级功能,从而轻松编写复杂的物理模拟,例如海洋模拟。

安装

Warp 以 来自 GitHub 的开源库 的形式提供。克隆存储库后,可以使用本地软件包管理器进行安装。对于 pip ,请使用以下命令:

pip install warp

初始化

导入后,必须显式初始化扭曲:

import warp as wp
wp.init()

推出内核

Warp 使用 Python 装饰器的概念来标记可以在 GPU 上执行的函数。例如,可以编写一个简单的半隐式粒子积分方案,如下所示:

@wp.kernel
def integrate(x: wp.array(dtype=wp.vec3), v: wp.array(dtype=wp.vec3), f: wp.array(dtype=wp.vec3), w: wp.array(dtype=float), gravity: wp.vec3, dt: float): # thread id tid = wp.tid() x0 = x[tid] v0 = v[tid] # Semi-implicit Euler step f_ext = f[tid] inv_mass = w[tid] v1 = v0 + (f_ext * inv_mass + gravity) * dt x1 = x0 + v1 * dt # store results x[tid] = x1 v[tid] = v1 

因为 Warp 是强类型的,所以应该为内核参数提供类型提示。要启动内核,请使用以下语法:

 wp.launch(kernel=simple_kernel, # kernel to launch dim=1024, # number of threads inputs=[a, b, c], # parameters device="cuda") # execution device

与 NumPy 等基于张量的框架不同, Warp 使用 kernel-based 编程模型。基于内核的编程与底层 GPU 执行模型更为匹配。对于需要细粒度条件逻辑和内存操作的模拟代码,这通常是一种更自然的表达方式。然而, Warp 以一种易于使用的方式公开了这种以线程为中心的编程模型,它不需要 GPU 体系结构的低级知识。

编译模型

启动内核会触发实时( JIT )编译管道,该管道会自动从 Python 函数定义生成 C ++/ CUDA 内核代码。

属于 Python 模块的所有内核都在运行时编译到动态库和 PTX 中。图 2 。显示了编译管道,其中包括遍历函数 AST 并将其转换为直线 CUDA 代码,然后编译并加载回 Python 进程。

A flowchart diagram showing how Python code gets compiled and converted by Warp into kernel level executable code.A flowchart diagram showing how Python code gets compiled and converted by Warp into kernel level executable code.图 2 。 Warp 内核的编译管道

这个 JIT 编译的结果被缓存。如果输入内核源代码不变,那么预编译的二进制文件将以低开销的方式加载。

记忆模型

Warp 中的内存分配通过warp.array类型公开。阵列封装了可能位于主机( CPU )或设备( GPU )内存中的底层内存分配。与张量框架不同, Warp 中的数组是强类型的,并存储内置结构的线性序列(vec3, matrix33, quat,等等)。

您可以从 Python 列表或 NumPy 数组中构造数组,或使用与 NumPy 和 PyTorch 类似的语法进行初始化:

# allocate an uninitizalized array of vec3s v = wp.empty(length=n, dtype=wp.vec3, device="cuda") # allocate a zero-initialized array of quaternions q = wp.zeros(length=n, dtype=wp.quat, device="cuda") # allocate and initialize an array from a numpy array # will be automatically transferred to the specified device v = wp.from_numpy(array, dtype=wp.vec3, device="cuda")

Warp 支持__array_interface____cuda_array_interface__协议,允许在基于张量的框架之间进行零拷贝数据视图。例如,要将数据转换为 NumPy ,请使用以下命令:

# automatically bring data from device back to host view = device_array.numpy()

特征

Warp 包含几个更高级别的数据结构,使实现模拟和几何处理算法更容易。

网格

三角形网格在仿真和计算机图形学中无处不在。 Warp 提供了一种内置类型,用于管理网格数据,该数据支持几何查询,例如最近点、光线投射和重叠检查。

下面的示例演示如何使用“扭曲”计算网格上距离输入位置数组最近的点。这种类型的计算是碰撞检测中许多算法的基础(图 3 )。 Warp 的网格查询使实现此类方法变得简单。

@wp.kernel
def project(positions: wp.array(dtype=wp.vec3), mesh: wp.uint64, output_pos: wp.array(dtype=wp.vec3), output_face: wp.array(dtype=int)): tid = wp.tid() x = wp.load(positions, tid) face_index = int(0) face_u = float(0.0) face_v = float(0.0) sign = float(0.0) max_dist = 2.0 if (wp.mesh_query_point(mesh, x, max_dist, sign, face_index, face_u, face_v)): p = wp.mesh_eval_position(mesh, face_index, face_u, face_v) output_pos[tid] = p output_face[tid] = face_index

稀疏卷

稀疏体对于表示大型域上的网格数据非常有用,例如复杂对象的符号距离场( SDF )或大规模流体流动的速度。 Warp 支持使用 NanoVDB 标准定义的稀疏卷。使用标准 OpenVDB 工具(如 Blender 、 Houdini 或 Maya )构造卷,然后在 Warp 内核内部采样。

您可以直接从磁盘或内存中的二进制网格文件创建卷,然后使用volumes API 对其进行采样:

wp.volume_sample_world(vol, xyz, mode) # world space sample using interpolation mode
wp.volume_sample_local(vol, uvw, mode) # volume space sample using interpolation mode
wp.volume_lookup(vol, ijk) # direct voxel lookup
wp.volume_transform(vol, xyz) # map point from voxel space to world space
wp.volume_transform_inv(vol, xyz) # map point from world space to volume space

使用卷查询,您可以以最小的内存开销高效地碰撞复杂对象。

散列网格

许多基于粒子的模拟方法,如离散元法( DEM )或平滑粒子流体动力学( SPH ),都涉及到在空间邻域上迭代以计算力的相互作用。哈希网格是一种成熟的数据结构,用于加速这些最近邻查询,特别适合 GPU 。

哈希网格由点集构成,如下所示:

哈希网格由点集构成,如下所示:

grid = wp.HashGrid(dim_x=128, dim_y=128, dim_z=128, device="cuda")
grid.build(points=p, radius=r)

创建散列网格后,可以直接从用户内核代码中查询它们,如以下示例所示,该示例计算所有相邻粒子位置的总和:

@wp.kernel
def sum(grid : wp.uint64, points: wp.array(dtype=wp.vec3), output: wp.array(dtype=wp.vec3), radius: float): tid = wp.tid() # query point p = points[tid] # create grid query around point query = wp.hash_grid_query(grid, p, radius) index = int(0) sum = wp.vec3() while(wp.hash_grid_query_next(query, index)): neighbor = points[index] # compute distance to neighbor point dist = wp.length(p-neighbor) if (dist <= radius): sum += neighbor output[tid] = sum

图 5 显示了粘性材料的 DEM 颗粒材料模拟示例。使用内置的哈希网格数据结构,您可以在不到 200 行 Python 中编写这样的模拟,并以交互速率运行超过 100K 个粒子。

使用扭曲散列网格数据可以轻松评估相邻粒子之间的成对力相互作用。

可微性

基于张量的框架,如 PyTorch 和 JAX ,提供了张量计算的梯度,非常适合于 ML 训练等应用。

Warp 的一个独特功能是能够生成 kernel code 的正向和反向版本。这使得编写可微模拟变得很容易,可以将梯度作为更大训练管道的一部分进行传播。一个常见的场景是,对网络层使用传统的 ML 框架,并使用 Warp 实现允许端到端差异性的模拟层。

当需要渐变时,应使用requires_grad=True创建阵列。例如,warp.Tape类可以记录内核启动并回放它们,以计算标量损失函数相对于内核输入的梯度:

tape = wp.Tape() # forward pass
with tape: wp.launch(kernel=compute1, inputs=[a, b], device="cuda") wp.launch(kernel=compute2, inputs=[c, d], device="cuda") wp.launch(kernel=loss, inputs=[d, l], device="cuda") # reverse pass
tape.backward(loss=l)

完成后向传递后,可通过Tape对象中的映射获得与输入相关的梯度:

# gradient of loss with respect to input a
print(tape.gradients[a])
A 3D image with multi-colored trace lines simulating a ball bouncing off a wall and hitting a black square suspended in mid-air away from the wall.A 3D image with multi-colored trace lines simulating a ball bouncing off a wall and hitting a black square suspended in mid-air away from the wall.
图 6 。一个轨迹优化的例子,其中球的初始速度被优化以击中黑色目标。每行显示 LBFGS 优化步骤的一次迭代的结果。

总结

在这篇文章中,我们介绍了 NVIDIA Warp ,这是一个 Python 框架,可以很容易地为 GPU 编写可微模拟代码。

关于作者

迈尔斯·麦克林( Miles Macklin )是NVIDIA 的首席工程师,致力于模拟技术。他从哥本哈根大学获得计算机科学博士学位,从事计算机图形学、基于物理学的动画和机器人学的研究。他在 ACM SIGGRAPH 期刊上发表了几篇论文,他的研究已经被整合到许多商业产品中,包括NVIDIA 的 PhysX 和 ISAAC 健身房模拟器。他最近的工作旨在为 GPU 上的可微编程开发健壮高效的框架。

Fred Oh 是 CUDA 、 CUDA on WSL 和 CUDA Python 的高级产品营销经理。弗雷德拥有加州大学戴维斯分校计算机科学和数学学士学位。他的职业生涯开始于一名 UNIX 软件工程师,负责将内核服务和设备驱动程序移植到 x86 体系结构。他喜欢《星球大战》、《星际迷航》和 NBA 勇士队。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 机器人
    +关注

    关注

    213

    文章

    29953

    浏览量

    214517
  • NVIDIA
    +关注

    关注

    14

    文章

    5353

    浏览量

    106868
  • 自动驾驶
    +关注

    关注

    790

    文章

    14400

    浏览量

    171536
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何在裸机环境运行KleidiAI微内核

    ,对 KleidiAI 进行了简要概述,并附有相关指南链接,其中详细说明了 Linux 环境运行 KleidiAI 矩阵乘法 (matmul) 微内核的分步操作,这份指南内容详实且
    的头像 发表于 08-08 15:16 ?2262次阅读
    如何在裸机<b class='flag-5'>环境</b><b class='flag-5'>中</b>运行KleidiAI微<b class='flag-5'>内核</b>

    linux虚拟环境调用Linux 版matlab编译的python库时出错

    、readme.txt、 requiredMCRProducts.txt、init.py、CAO_python.ctf。 linux环境按照以下步骤安装matlab runtime
    发表于 07-18 10:40

    进迭时空同构融合RISC-V AI CPU的Triton算子编译器实践

    Triton是由OpenAI开发的一个开源编程语言和编译器,旨在简化高性能GPU内核编写。它提供了类似Python的语法,并通过高级抽象降低了GPU编程的复杂性,同时保持了高性能。目前
    的头像 发表于 07-15 09:04 ?583次阅读
    进迭时空同构融合RISC-V AI CPU的Triton算子编译器实践

    基础篇3:掌握Python的条件语句与循环

    通过学习条件语句和循环,您能够编写出能够根据不同情况和条件作出决策的Python程序。这些结构在编程中非常常见,对于提高编程能力和构建复杂程序至关重要。接下来的学习和实践,不断练
    发表于 07-03 16:13

    ?如何在虚拟环境中使用 Python,提升你的开发体验~

    RaspberryPiOS预装了Python,你需要使用其虚拟环境来安装包。今天出版的最新一期《TheMagPi》杂志刊登了我们文档负责人NateContino撰写的一篇实用教程,帮助你入门
    的头像 发表于 03-25 09:34 ?424次阅读
    ?如何在虚拟<b class='flag-5'>环境</b>中使用 <b class='flag-5'>Python</b>,提升你的开发体验~

    零基础入门:如何在树莓派上编写和运行Python程序?

    在这篇文章,我将为你简要介绍Python程序是什么、Python程序可以用来做什么,以及如何在RaspberryPi上编写和运行一个简单的Pyth
    的头像 发表于 03-25 09:27 ?995次阅读
    零基础入门:如何在树莓派上<b class='flag-5'>编写</b>和运行<b class='flag-5'>Python</b>程序?

    Python嵌入式系统的应用场景

    你想把你的职业生涯提升到一个新的水平?Python嵌入式系统中正在成为一股不可缺少的新力量。尽管传统上嵌入式开发更多地依赖于C和C++语言,Python的优势在于其简洁的语法、丰富的库和快速的开发周期,这使得它在某些嵌入式场景
    的头像 发表于 03-19 14:10 ?840次阅读

    晶圆的环吸方案相比其他吸附方案,对于测量晶圆 BOW/WARP 的影响

    半导体制造领域,晶圆的加工精度和质量控制至关重要,其中对晶圆 BOW(弯曲度)和 WARP(翘曲度)的精确测量更是关键环节。不同的吸附方案被应用于晶圆测量过程,而晶圆的环吸方案因其独特
    的头像 发表于 01-09 17:00 ?639次阅读
    晶圆的环吸方案相比其他吸附方案,对于测量晶圆 BOW/<b class='flag-5'>WARP</b> 的影响

    晶圆的TTV,BOW,WARP,TIR是什么?

    晶圆的TTV、BOW、WARP、TIR是评估晶圆质量和加工精度的重要指标,以下是它们的详细介绍: TTV(Total Thickness Variation,总厚度偏差) 定义:晶圆的总厚度变化
    的头像 发表于 12-17 10:01 ?1972次阅读
    晶圆的TTV,BOW,<b class='flag-5'>WARP</b>,TIR是什么?

    逻辑异或运算符Python的用法

    Python的 ^ 符号实际上是一个按位异或运算符,用于对整数的二进制表示进行异或操作。 尽管如此,我们仍然可以通过一些方法来实现逻辑异或的功能,即当两个布尔值不同时为真,相同时为假。这可以通过使用逻辑运算符来实现,而不是直接使用 ^ (因为 ^
    的头像 发表于 11-19 09:46 ?958次阅读

    Python环境下的代理服务器搭建与自动化管理

    Python环境下搭建与自动化管理代理服务器是一项涉及网络编程和自动化技术的综合任务。
    的头像 发表于 11-14 07:31 ?773次阅读

    行业动态 | 英伟达2024年将出货10亿个RISC-V 内核

    据Tomshardware援引@NickBrownHPC的爆料称,尽管英伟达(NVIDIA)的GPU依赖于其专有的CUDA内核,这些内核具有其指令集架构并支持各种数据格式。但是本月的
    的头像 发表于 10-29 08:07 ?790次阅读
    行业动态 | 英伟达2024年将出货10亿个RISC-V <b class='flag-5'>内核</b>

    Python多线程和多进程的区别

    Python作为一种高级编程语言,提供了多种并发编程的方式,其中多线程与多进程是最常见的两种方式之一。本文中,我们将探讨Python多线程与多进程的概念、区别以及如何使用线程池与进
    的头像 发表于 10-23 11:48 ?1123次阅读
    <b class='flag-5'>Python</b><b class='flag-5'>中</b>多线程和多进程的区别

    怎么TMDSEVM6678: 6678自带的FFT接口和CUDA提供CUFFT函数库选择?

    请教一下gpgpu上包括4个Riscv cpu和一个DPU, 没有6678,要替换原来信号处理用的6678,该怎么6678自带的FFT接口和CUDA提供CUFFT函数库选择?
    发表于 09-27 07:20

    linux驱动程序如何加载进内核

    Linux系统,驱动程序是内核与硬件设备之间的桥梁。它们允许内核与硬件设备进行通信,从而实现对硬件设备的控制和管理。 驱动程序的编写
    的头像 发表于 08-30 15:02 ?1221次阅读