【Triton教程】向量相加

Triton 是一种用于并行编程的语言和编译器。它旨在提供一个基于 Python 的编程环境,以高效编写自定义 DNN 计算内核,并能够在现代 GPU 硬件上以最大吞吐量运行。

更多 Triton 中文文档可访问 →https://triton.hyper.ai/

在本教程中,你将使用 Triton 编写一个简单的向量相加 (vector addition) 程序。

你将了解:

  • Triton 的基本编程模型
  • 用于定义 Triton 内核的 triton.jit 装饰器 (decorator)
  • 验证和基准测试自定义算子与原生参考实现的最佳实践

计算内核

import torch
import triton
import triton.language as tl@triton.jit
def add_kernel(x_ptr,  # *Pointer* to first input vector. 指向第一个输入向量的指针。y_ptr,  # *Pointer* to second input vector. 指向第二个输入向量的指针。output_ptr,  # *Pointer* to output vector. 指向输出向量的指针。n_elements,  # Size of the vector. 向量的大小。BLOCK_SIZE: tl.constexpr,  # Number of elements each program should process. 每个程序应处理的元素数量。# NOTE: `constexpr` so it can be used as a shape value. 注意:`constexpr` 因此它可以用作形状值。):# There are multiple 'programs' processing different data. We identify which program# 有多个“程序”处理不同的数据。需要确定是哪一个程序:pid = tl.program_id(axis=0)  # We use a 1D launch grid so axis is 0. 使用 1D 启动网格,因此轴为 0# This program will process inputs that are offset from the initial data.# 该程序将处理相对初始数据偏移的输入。# For instance, if you had a vector of length 256 and block_size of 64, the programs would each access the elements [0:64, 64:128, 128:192, 192:256].# 例如,如果有一个长度为 256, 块大小为 64 的向量,程序将各自访问 [0:64, 64:128, 128:192, 192:256] 的元素。# Note that offsets is a list of pointers:# 注意 offsets 是指针列表:block_start = pid * BLOCK_SIZEoffsets = block_start + tl.arange(0, BLOCK_SIZE)# Create a mask to guard memory operations against out-of-bounds accesses.# 创建掩码以防止内存操作超出边界访问。mask = offsets < n_elements# Load x and y from DRAM, masking out any extra elements in case the input is not a multiple of the block size.# 从 DRAM 加载 x 和 y,如果输入不是块大小的整数倍,则屏蔽掉任何多余的元素。x = tl.load(x_ptr + offsets, mask=mask)y = tl.load(y_ptr + offsets, mask=mask)output = x + y# Write x + y back to DRAM.# 将 x + y 写回 DRAM。tl.store(output_ptr + offsets, output, mask=mask)

创建一个辅助函数从而: (1) 生成 z 张量,(2) 用适当的 grid/block sizes 将上述内核加入队列:

def add(x: torch.Tensor, y: torch.Tensor):# We need to preallocate the output.# 需要预分配输出。output = torch.empty_like(x)assert x.is_cuda and y.is_cuda and output.is_cudan_elements = output.numel()# The SPMD launch grid denotes the number of kernel instances that run in parallel.# SPMD 启动网格表示并行运行的内核实例的数量。# It is analogous to CUDA launch grids. It can be either Tuple[int], or Callable(metaparameters) -> Tuple[int].# 它类似于 CUDA 启动网格。它可以是 Tuple[int],也可以是 Callable(metaparameters) -> Tuple[int]# In this case, we use a 1D grid where the size is the number of blocks:# 在这种情况下,使用 1D 网格,其中大小是块的数量:grid = lambda meta: (triton.cdiv(n_elements, meta['BLOCK_SIZE']), )# NOTE:# 注意:#  - Each torch.tensor object is implicitly converted into a pointer to its first element.#  - 每个 torch.tensor 对象都会隐式转换为其第一个元素的指针。#  - `triton.jit`'ed functions can be indexed with a launch grid to obtain a callable GPU kernel.#  - `triton.jit` 函数可以通过启动网格索引来获得可调用的 GPU 内核。#  - Don't forget to pass meta-parameters as keywords arguments.#  - 不要忘记以关键字参数传递元参数。add_kernel[grid](x, y, output, n_elements, BLOCK_SIZE=1024)# We return a handle to z but, since `torch.cuda.synchronize()` hasn't been called, the kernel is still running asynchronously at this point.# 返回 z 的句柄,但由于 `torch.cuda.synchronize()` 尚未被调用,此时内核仍在异步运行。return output

使用上述函数计算两个 torch.tensor 对象的 element-wise sum,并测试其正确性:

torch.manual_seed(0)
size = 98432
x = torch.rand(size, device='cuda')
y = torch.rand(size, device='cuda')
output_torch = x + y
output_triton = add(x, y)
print(output_torch)
print(output_triton)
print(f'The maximum difference between torch and triton is 'f'{torch.max(torch.abs(output_torch - output_triton))}')

Out:

tensor([1.3713, 1.3076, 0.4940,  ..., 0.6724, 1.2141, 0.9733], device='cuda:0')tensor([1.3713, 1.3076, 0.4940,  ..., 0.6724, 1.2141, 0.9733], device='cuda:0')The maximum difference between torch and triton is 0.0

现在准备就绪。

基准测试

在 size 持续增长的向量上对自定义算子进行基准测试,从而比较其与 PyTorch 的性能差异。为了方便操作,Triton 提供了一系列内置工具,允许开发者简洁地绘制自定义算子在不同问题规模 (problem sizes) 下的的性能图。

@triton.testing.perf_report(triton.testing.Benchmark(x_names=['size'],  # Argument names to use as an x-axis for the plot. 用作绘图 x 轴的参数名称。x_vals=[2**i for i in range(12, 28, 1)],  # Different possible values for `x_name`. `x_name` 的不同可能值。x_log=True,  # x axis is logarithmic. x 轴为对数。line_arg='provider',  # Argument name whose value corresponds to a different line in the plot. 参数名称,其值对应于绘图中的不同线条。line_vals=['triton', 'torch'],  # Possible values for `line_arg`. `line_arg` 的可能值。line_names=['Triton', 'Torch'],  # Label name for the lines. 线条的标签名称。styles=[('blue', '-'), ('green', '-')],  # Line styles. 线条样式。ylabel='GB/s',  # Label name for the y-axis. y 轴标签名称。plot_name='vector-add-performance',  # Name for the plot. Used also as a file name for saving the plot. 绘图名称。也用作保存绘图的文件名。args={},  # Values for function arguments not in `x_names` and `y_name`. 不在 `x_names` 和 `y_name` 中的函数参数值。))
def benchmark(size, provider):x = torch.rand(size, device='cuda', dtype=torch.float32)y = torch.rand(size, device='cuda', dtype=torch.float32)quantiles = [0.5, 0.2, 0.8]if provider == 'torch':ms, min_ms, max_ms = triton.testing.do_bench(lambda: x + y, quantiles=quantiles)if provider == 'triton':ms, min_ms, max_ms = triton.testing.do_bench(lambda: add(x, y), quantiles=quantiles)gbps = lambda ms: 3 * x.numel() * x.element_size() / ms * 1e-6return gbps(ms), gbps(max_ms), gbps(min_ms)

运行上述装饰函数 (decorated function)。输入查看性能数据,输入 show_plots=True 绘制结果, 以及/或者输入 save_path='/path/to/results/' 将其与原始 CSV 数据一起保存到磁盘:

benchmark.run(print_data=True, show_plots=True)

在这里插入图片描述

out:

在这里插入图片描述

Download Jupyter notebook: 01-vector-add.ipynb
Download Python source code: 01-vector-add.py
Download zipped: 01-vector-add.zip

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/453853.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang | Leetcode Golang题解之第485题最大连续1的个数

题目&#xff1a; 题解&#xff1a; func findMaxConsecutiveOnes(nums []int) (maxCnt int) {cnt : 0for _, v : range nums {if v 1 {cnt} else {maxCnt max(maxCnt, cnt)cnt 0}}maxCnt max(maxCnt, cnt)return }func max(a, b int) int {if a > b {return a}return …

Android TextView实现一串文字特定几个字改变颜色

遇到一个需求&#xff0c;让Android端实现给定一个字符串指定下标的几个字颜色与其他字颜色不一致。 主要是用ForegroundColorSpan这个API来传入颜色值&#xff0c;用SpannableString来设置指定索引下标的字的颜色值。 这里通过给定一个输入文字描述框&#xff0c;要求输入指定…

线上问题排查-常见的线上问题

一、线上问题排查思路 明确问题&#xff1a;首先&#xff0c;需要明确线上出现了什么问题。这包括了解问题的具体表现、发生的时间、影响的范围等。通过收集用户反馈、查看监控系统告警等方式&#xff0c;收集问题相关信息。收集信息&#xff1a;收集与问题相关的各种信息&…

BIO CHINA2025生物发酵展高歌猛进,规模再升级, 亮点及活动发布,精彩就在此刻!

BIO CHINA2025生物发酵展高歌猛进&#xff0c;规模再升级&#xff0c; 亮点及活动发布&#xff0c;精彩就在此刻&#xff01; 目前国家高度重视生物经济与生物技术产业的发展&#xff0c;出台了一系列政策措施支持行业发展。生物发酵行业作为现代生物经济的重要支柱&#xff0…

【原创】java+ssm+mysql校园在线答疑管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

Scrapy | 爬取笑话网来认识继承自Spider的crawlspider爬虫类

crawlspider 1. 创建crawlspider爬虫2. 实战-爬取笑话网笑话 本篇内容旨在拓展视野和知识&#xff0c;了解crawlspider的使用即可&#xff0c;主要熟悉掌握spider类的使用 CrawlSpider 提供了一种更高级的方法来定义爬取规则&#xff0c;而无需编写大量的重复代码。它基于规则…

Pseudo Multi-Camera Editing 数据集:通过常规视频生成的伪标记多摄像机推荐数据集,显著提升模型在未知领域的准确性。

2024-10-19&#xff0c;由伊利诺伊大学厄巴纳-香槟分校和香港城市大学的研究团队提出了一种创新方法&#xff0c;通过将常规视频转换成伪标记的多摄像机视角推荐数据集&#xff0c;有效解决了在未知领域中模型泛化能力差的问题。数据集的创建&#xff0c;为电影、电视和其他媒体…

【论文学习与撰写】,论文word文档中出现乱码的情况,文档中显示的乱码,都是英文字母之类的,但打印预览是正常的

目录 1、问题 2、解决方法 1、问题 写论文的时候&#xff0c;有时会出现乱码的情况&#xff0c; 如下图&#xff0c;这种情况&#xff0c; 可是 在打印预览的时候&#xff0c;就显示的正常 如下图&#xff0c; 2、解决方法 既然是文档正文显示错误&#xff0c;显示乱码&…

typeAliases以及mappers

typeAliases 我们来观察一下CarMapper.xml中的配置信息&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd&qu…

Spark数据源的读取与写入、自定义函数

1. 数据源的读取与写入 1.1 数据读取 读文件 read.jsonread.csv csv文件由两个部分组成&#xff1a;头部数据&#xff08;也就是字段数据&#xff09;、行数据。 read.orc 读数据库 read.jdbc(jdbc连接地址,table‘表名’,properties{‘user’用户名,‘password’密码,‘driv…

万能工具箱小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 万能工具箱小程序源码系统是一款集多种实用工具于一体的综合性平台。它为用户提供了便捷的操作界面和丰富的功能选项&#xff0c;满足了人们在日常生活和工作中的各种需求。 该系统采用先进的技术架构&#xff0c;具备高度的稳定性和可靠性。无论是在处理大量数据还…

python excel如何转成json,并且如何解决excel转成json时中文汉字乱码的问题

1.解决excel转成json时中文汉字乱码的问题 真的好久没有打开这个博客也好久没有想起来记录一下问题了&#xff0c;今天将表格测试集转成json格式的时候遇到了汉字都变成了乱码的问题&#xff0c;虽然这不是个大问题&#xff0c;但是编码问题挺烦人的&#xff0c;乱码之后像下图…

Flink窗口分配器WindowAssigner

前言 Flink 数据流经过 keyBy 分组后&#xff0c;下一步就是 WindowAssigner。 WindowAssigner 定义了 stream 中的元素如何被分发到各个窗口&#xff0c;元素可以被分发到一个或多个窗口中&#xff0c;Flink 内置了常用的窗口分配器&#xff0c;包括&#xff1a;tumbling wi…

【C++篇】栈的层叠与队列的流动:在 STL 的节奏中聆听算法的静谧旋律

文章目录 C 栈与队列详解&#xff1a;基础与进阶应用前言第一章&#xff1a;栈的介绍与使用1.1 栈的介绍1.2 栈的使用1.2.1 最小栈1.2.2 示例与输出 1.3 栈的模拟实现 第二章&#xff1a;队列的介绍与使用2.1 队列的介绍2.2 队列的使用2.2.1 示例与输出 2.3 队列的模拟实现2.3.…

【linux】线程(二)

10. pthread_t 类型 注意&#xff1a; 每一个线程的库级别的tcb的起始地址&#xff0c;就是线程的 tid每一个线程都有自己独立的栈结构线程和线程之间&#xff0c;也是可以被其他线程看到并访问的&#xff08;比如全局函数&#xff09; 代码 如果想要进程拥有私人的全局变量(即…

拥抱“新市民” ,数字银行的“谋与变”

【潮汐商业评论/原创】 数字银行&#xff0c;既是金融行业的创新物种&#xff0c;其在发展的过程中也彰显着普惠金融的基因。 “我劝你买点银行理财吧&#xff0c;选一家靠谱的银行就是最靠谱的理财方式了&#xff0c;踏踏实实地把钱存银行里面不会有问题的”&#xff0c;周日…

SpringBoot篇(二、制作SpringBoot程序)

目录 一、代码位置 二、四种方式 1. IDEA联网版 2. 官网 3. 阿里云 4. 手动 五、在IDEA中隐藏指定文件/文件夹 六、复制工程-快速操作 七、更改引导类别名 一、代码位置 二、四种方式 1. IDEA联网版 2. 官网 官网制作&#xff1a;Spring Boot 3. 阿里云 阿里云版制…

react18中的计算属性及useMemo的性能优化技巧

react18里面的计算属性和使用useMemo来提升组件性能的方法 计算属性 实现效果 代码实现 函数式组件极简洁的实现&#xff0c;就这样 import { useState } from "react"; function FullName() {const [firstName, setFirstName] useState("");const [la…

AlDente Pro for Mac电脑 充电限制保护工具 安装教程【简单,轻松上手】

Mac分享吧 文章目录 AlDente Pro for Mac 充电限制保护工具 安装完成&#xff0c;软件打开效果一、AlDente Pro for Mac 充电限制保护工具 Mac电脑版——v1.28.41️⃣&#xff1a;下载软件2️⃣&#xff1a;安装软件&#xff0c;将安装包从左侧拖入右侧文件夹中&#xff0c;等…

c++初阶--string类(使用)

大家好&#xff0c;许久不见&#xff0c;今天我们来学习c中的string类&#xff0c;在这一部分&#xff0c;我们首先应该学习一下string类的用法&#xff0c;然后再试着自己去实现一下string类。 在这里&#xff0c;我使用的是这个网站来查找的string类&#xff0c;这里面的内容…