用Roofline模型去分析pytorch和Triton算子

用Roofline模型去分析pytorch和Triton算子

  • 1.参考链接
  • 2.测试环境
  • 3.安装相关依赖
  • 4.锁频
  • 5.获取理论算力
  • 6.创建测试脚本
  • 7.运行测试程序生成Roofline图
  • 8.NVIDIA Nsight Compute生成Roofline
  • 9.效果图
    • A.nn.Linear
    • B.Triton实现

本文演示了如何用Roofline模型去分析pytorch和Triton算子
遗留问题:NVIDIA Nsight Compute中的Peak Work是怎么算出来的,又不是峰值算力

1.参考链接

  • roofline-overview
  • rtx-3060
  • OpenAI Triton

2.测试环境

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.161.07             Driver Version: 535.161.07   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce RTX 3060        On  | 00000000:03:00.0 Off |                  N/A |
|  0%   48C    P5              29W / 170W |     18MiB / 12288MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
torch==2.3.1+cu121

3.安装相关依赖

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64
export PATH=$PATH:/usr/local/cuda/bin
export CUDA_HOME=$CUDA_HOME:/usr/local/cuda
pip install pycuda

4.锁频

MAX_Graphics_CLOCK=`nvidia-smi -q -d SUPPORTED_CLOCKS | grep 'Graphics' | sed 's/[^0-9]//g' | sort -n | uniq | tail -n 1`
MAX_Memory_CLOCK=`nvidia-smi -q -d SUPPORTED_CLOCKS | grep 'Memory' | sed 's/[^0-9]//g' | sort -n | uniq | tail -n 1`
nvidia-smi -pm 1
nvidia-smi -lgc $MAX_Graphics_CLOCK,$MAX_Graphics_CLOCK
nvidia-smi -i 0 -ac $MAX_Memory_CLOCK,$MAX_Graphics_CLOCK
nvidia-smi -q -d CLOCK

5.获取理论算力

tee Theoretical_FLOPS.py <<-'EOF'
import pycuda.driver as cuda
import pycuda.autoinitdef get_gpu_compute_capability_and_clock_rate():device = cuda.Device(0)compute_capability = device.compute_capability()clock_rate = device.get_attribute(cuda.device_attribute.CLOCK_RATE)  # in kHzsm_count = device.get_attribute(cuda.device_attribute.MULTIPROCESSOR_COUNT)cores_per_sm = get_cuda_cores_per_sm(compute_capability)return compute_capability, clock_rate, sm_count, cores_per_smdef get_cuda_cores_per_sm(compute_capability):major, minor = compute_capabilityif major == 2:return 32elif major == 3:return 192elif major == 5:return 128elif major == 6 and minor in [0, 1]:return 64elif major == 6 and minor == 2:return 128elif major == 7 and minor in [0, 5]:return 64elif major == 7 and minor == 2:return 64elif major == 8 and minor in [0, 6]:return 128else:raise ValueError("Unknown compute capability")def calculate_theoretical_flops(clock_rate, sm_count, cores_per_sm):clock_rate_hz = clock_rate * 1e3  # Convert kHz to Hzflops = clock_rate_hz * sm_count * cores_per_sm * 2  # 2 FLOPs per clock per core (FMA)return flopscompute_capability, clock_rate, sm_count, cores_per_sm = get_gpu_compute_capability_and_clock_rate()
theoretical_flops = calculate_theoretical_flops(clock_rate, sm_count, cores_per_sm)
print(f"GPU compute capability: {compute_capability}")
print(f"Clock rate (kHz): {clock_rate}")
print(f"Number of SMs: {sm_count}")
print(f"Cores per SM: {cores_per_sm}")
print(f"Theoretical FLOPS for float32: {theoretical_flops / 1e12} TFLOPS")
EOF
python Theoretical_FLOPS.py

输出

GPU compute capability: (8, 6)
Clock rate (kHz): 1852000
Number of SMs: 28
Cores per SM: 128
Theoretical FLOPS for float32: 13.275136 TFLOPS

6.创建测试脚本

tee roofline_model.py <<-'EOF'
import sys
import torch
import torch.nn as nn
import triton
import triton.language as tl
import math
import torch
import torch.nn as nn
from fvcore.nn import FlopCountAnalysis, ActivationCountAnalysis
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.font_manager import FontProperties
import os
import argparse# 定义一个测试模型
class SimpleModel(nn.Module):def __init__(self,input_features,output_features):super(SimpleModel, self).__init__()self.fc1 = nn.Linear(input_features,output_features,bias=False)def forward(self, x):x = self.fc1(x)return x@triton.jit
def sgemm_kernel(A, B, C,M, N, K,stride_am, stride_ak,stride_bk, stride_bn,stride_cm, stride_cn,BLOCK_SIZE: tl.constexpr
):""" Kernel for computing C = A @ B """# Define the program idspid_m = tl.program_id(0)pid_n = tl.program_id(1)# Create base pointers for A and B and Coffs_am = pid_m * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)offs_bn = pid_n * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)offs_ak = tl.arange(0, BLOCK_SIZE)a_ptrs = A + (stride_am * offs_am[:, None] + stride_ak * offs_ak[None, :])b_ptrs = B + (stride_bk * offs_ak[:, None] + stride_bn * offs_bn[None, :])# Initialize accumulatoracc = tl.zeros((BLOCK_SIZE, BLOCK_SIZE), dtype=tl.float32)# Loop over K dimensionfor k in range(0, K, BLOCK_SIZE):a = tl.load(a_ptrs, mask=offs_am[:, None] < M)b = tl.load(b_ptrs, mask=offs_bn[None, :] < N)acc += tl.dot(a, b)a_ptrs += BLOCK_SIZE * stride_akb_ptrs += BLOCK_SIZE * stride_bk# Write back resultsc_ptrs = C + stride_cm * offs_am[:, None] + stride_cn * offs_bn[None, :]tl.store(c_ptrs, acc, mask=(offs_am[:, None] < M) & (offs_bn[None, :] < N))class TritonLinear(nn.Module):def __init__(self, in_features, out_features):super(TritonLinear, self).__init__()self.in_features = in_featuresself.out_features = out_featuresself.weight = nn.Parameter(torch.randn(out_features, in_features).float()).cuda()def forward(self, x):assert x.shape[1] == self.in_featuresout = torch.empty((x.shape[0], self.out_features), device=x.device, dtype=x.dtype).cuda()grid = lambda META: (math.ceil(x.shape[0] / META['BLOCK_SIZE']), math.ceil(self.out_features / META['BLOCK_SIZE']))sgemm_kernel[grid](x, self.weight, out,x.shape[0], self.out_features, self.in_features,x.stride(0), x.stride(1),self.weight.stride(0), self.weight.stride(1),out.stride(0), out.stride(1),BLOCK_SIZE=64)return outdef main(args):# 模型和输入数据input_features = 8192output_features = 8192batch_size = 8192model = SimpleModel(input_features,output_features)input_data = torch.randn(batch_size, input_features)    test_count=10# 计算 FLOPs 和内存访问量flops = FlopCountAnalysis(model, input_data).total()*test_countactivations = ActivationCountAnalysis(model, input_data).total() + input_data.numel()print("activations:",activations)# 计算参数个数params = sum(p.numel() for p in model.parameters())# 内存访问量假定为 activations 和params 乘以 4 字节(假设 activations 和 params 是 float32 类型)activation_memory_access = activations * 4params_memory_access = params * 4memory_access = activation_memory_access + params_memory_accessmemory_access=memory_access*test_countif args.triton_kernel:model = TritonLinear(in_features=input_features, out_features=output_features)else:model=model.cuda()input_data=input_data.float().cuda()for i in range(5):output = model(input_data) torch.cuda.synchronize()if args.warmup_only:returnif False:# 设置 CUDA 事件用于计算执行时间start_event = torch.cuda.Event(enable_timing=True)end_event = torch.cuda.Event(enable_timing=True)start_event.record()for _ in range(test_count):output = model(input_data)end_event.record()torch.cuda.synchronize()total_cuda_time = start_event.elapsed_time(end_event) / 1000  # 转换为秒else:# 使用 PyTorch Profiler 计算 FLOPs、内存访问和执行时间with torch.profiler.profile(activities=[torch.profiler.ProfilerActivity.CUDA]) as prof:for _ in range(test_count):output = model(input_data)key_averages = prof.key_averages()for ev in key_averages:print(ev)total_cuda_time = sum([event.self_cuda_time_total for event in key_averages if event.key.find("sgemm")>=0]) / 1e6  # 转换至秒# FLOPs 转换至 GFLOPsflops_measured_glops = flops / 1e9# 内存带宽测量memory_access_gb=memory_access/ 1e9bandwidth_measured = memory_access_gb / total_cuda_time  # 单位:GB/sprint("bandwidth_measured:",bandwidth_measured)# GPU 的峰值性能和带宽peak_performance = 13.275136  * 1e3  # 单位:GFLOPsmemory_bandwidth = 360.0  # 单位:GB/s# 计算 Roofline 模型中的数据点Io = np.logspace(-2,4,100) #GFLOPs/GBperformance = np.minimum(peak_performance, Io * memory_bandwidth)  #不同计算密度下的最大FLOPs/S,上限为峰值算力peak_performance# 绘制 Roofline 模型plt.figure(figsize=(10, 6))thresold=0.75# 设置字体以支持中文font_path = 'simsun.ttc'  # 在这里替换为你的字体路径font_prop = FontProperties(fname=font_path)# Bandwidth Boundx=Io[Io<(peak_performance / memory_bandwidth)]plt.fill_between(x, np.minimum(peak_performance, x * memory_bandwidth)*thresold,np.minimum(peak_performance, x * memory_bandwidth),color='lightblue', alpha=0.6, label='Bandwidth Bound')# Compute Boundx2=Io[Io>=(peak_performance / memory_bandwidth)]plt.fill_between(x2, np.minimum(peak_performance, x2 * memory_bandwidth)*thresold, np.minimum(peak_performance, x2 * memory_bandwidth), color='green', alpha=0.6, label='Compute Bound')# 绘制低性能区域plt.fill_between(Io, 0, np.minimum(peak_performance, Io * memory_bandwidth)*thresold,color='gray', alpha=0.6, label='poor performance')plt.axhline(y=peak_performance, color='b', linestyle='--', label=f'峰值计算能力:{peak_performance/1e3:.2f}TFLOPs')plt.axvline(x=peak_performance / memory_bandwidth, color='g', linestyle='--', label=f'{peak_performance / memory_bandwidth:.2f}GFLOPs/GB')plt.loglog(Io, performance, label='Roofline')arithmetic_intensity_measured=flops_measured_glops/memory_access_gb #GFLOPs/GB(算法的静态属性)point_y = arithmetic_intensity_measured*bandwidth_measuredplt.scatter(arithmetic_intensity_measured, point_y, c='r',label=f'Measured Points {point_y/1e3:.2f} TFLOPs/sec {point_y*100/peak_performance:.2f}%')plt.xlabel('操作强度 [GFLOPs/GB]', fontproperties=font_prop)plt.ylabel('性能 [GFLOPs/sec]', fontproperties=font_prop)plt.title('Roofline 模型', fontproperties=font_prop)plt.legend(prop=font_prop)# 保存图片而不显示plt.savefig('roofline_model.png')plt.close()print(f"FLOPs: {flops} FLOPs")print(f"内存访问量: {memory_access} 字节")print(f"执行时间: {total_cuda_time:.4f} 秒")print(f"理论值的:{point_y*100/peak_performance:.2f}%")parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument("--warmup_only", action="store_true", help="warmup_only")
parser.add_argument("--triton_kernel", action="store_true", help="triton_kernel")args = parser.parse_args()
main(args)
EOF

7.运行测试程序生成Roofline图

python roofline_model.py
python roofline_model.py --triton_kernel

输出

FLOPs: 5497558138880 FLOPs
内存访问量: 8053063680 字节
执行时间: 1.3862 秒
理论值的:29.87%FLOPs: 5497558138880 FLOPs
内存访问量: 8053063680 字节
执行时间: 1.0957 秒
理论值的:37.80%

8.NVIDIA Nsight Compute生成Roofline

/usr/local/cuda/bin/ncu -f --section SpeedOfLight_HierarchicalSingleRooflineChart \--section ComputeWorkloadAnalysis --section MemoryWorkloadAnalysis \--target-processes all --export roofline_report python roofline_model.py --warmup_only/usr/local/cuda/bin/ncu -f --section SpeedOfLight_HierarchicalSingleRooflineChart \--section ComputeWorkloadAnalysis --section MemoryWorkloadAnalysis \--target-processes all --export roofline_triton_kernel_report python roofline_model.py --warmup_only --triton_kernel

9.效果图

A.nn.Linear

在这里插入图片描述
在这里插入图片描述

B.Triton实现

请添加图片描述
在这里插入图片描述

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

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

相关文章

Vue2 - 项目上线后生产环境中去除console.log的输出以及断点的解决方案

前言 当你准备将Vue.js应用程序部署到生产环境时,一个关键的优化步骤是移除代码中的所有 console.log 语句以及断点。在开发阶段,console.log 是一个非常有用的调试工具,但在生产环境中保留它们可能会影响性能和安全性。在本文中,我将向你展示如何通过使用Vue CLI 2来自动…

【LLVM】学习使用PGO优化

笔者在查看PGO优化时看到了本站的这篇文章&#xff0c;其中代码和命令行部分贴上了序号&#xff0c;且命令行带上了$符号&#xff0c;不便于读者调试。 遂将代码重新整理到gitee&#xff0c;链接在此。 汇编代码分析 目前笔者使用的llvm版本为llvm-19&#xff0c;主要改动发生…

Postgresql从小白到高手 九 : psql高级查询及内部视图使用

Postgresql从小白到高手 九:pgsql 复杂查询及内部表高级查询 文章目录 Postgresql从小白到高手 九:pgsql 复杂查询及内部表高级查询一、多表查询二、pgsql内部表1.内部表2.内部表查询应用 一、多表查询 内联 &#xff1a;inner join on 简写 join on 结果集只有符合 筛选条件…

【Golang】Steam 创意工坊 Mod 文件夹批量重命名

本文将介绍一个使用Go语言编写的脚本&#xff0c;其主要功能是解析XML文件并基于解析结果重命名文件夹。这个脚本适用于需要对文件夹进行批量重命名&#xff0c;并且重命名规则依赖于XML文件内容的情况。 脚本功能概述 Steam创意工坊下载的Mod文件夹批量重命名为id名称 运行前…

maven仓库的作用以及安装 , DEA配置本地Maven

ay12-maven 主要内容 Maven的作用Maven仓库的作用Maven的坐标概念Maven的安装IDEA配置本地Maven 一、maven概述 1.1、项目开发中的问题 1、我的项目依赖一些jar包&#xff0c;我把他们放在哪里&#xff1f;直接拷贝到项目的lib文件夹中?如果我开发的第二个项目还是需要上面…

Linux系统编程(七)进程间通信IPC

进程间通讯的7种方式_进程间通信的几种方法-CSDN博客 管道 pipe&#xff08;命名管道和匿名管道&#xff09;&#xff1b;信号 signal&#xff1b;共享内存&#xff1b;消息队列&#xff1b;信号量 semaphore&#xff1b;套接字 socket&#xff1b; 1. 管道 内核提供&#x…

亿发进销存管理系统+:多终端无缝协同,实现经营销售场景全覆盖

亿发软件凭借产品、市场、业务的深入理解&#xff0c;在进销存基础上进行了延伸&#xff0c;推出多终端、一体化的“进销存管理系统”多元产品矩阵。对企业经营中进货、出货、销售、付款等进行全程跟踪管理。有效辅助企业解决业务管理、销售管理、库存管理、财务管理等一系列问…

如何做到高级Kotlin强化实战?(一)

高级Kotlin强化实战&#xff08;一&#xff09; 第一章 Kotlin 入门教程1.Kotlin 入门介绍2.Kotlin 与 Java 比较 第一章 Kotlin 入门教程 1.Kotlin 入门介绍 Kotlin 概述 Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言。它主要是 JetBrains 开发团队所开发出来的编程…

卸载vmware时2503,2502报错的解决办法

1.背景 windows 卸载vmware时&#xff0c;显示2503报错&#xff0c;无法完全卸载 2. 解决方案 2.1 参考安装报错2502&#xff0c;2503的处理方式 文献&#xff1a;https://blog.csdn.net/zhangvalue/article/details/80309828 2.1 步骤&#xff1a; 2.1.1 cmd 管理员打开…

实时美颜技术解析:视频美颜SDK如何改变直播行业

实时美颜技术的出现&#xff0c;尤其是视频美颜SDK的应用&#xff0c;正逐渐改变着直播行业的生态。 一、实时美颜技术的原理 实时美颜技术利用人工智能和图像处理算法&#xff0c;对视频中的人物面部进行优化和修饰。该技术通常包含以下几个步骤&#xff1a; 1.人脸检测和识…

MMCV【mmclassification】 从0到1 之 Docker 容器环境搭建步骤总结

🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 📙 Linux 下 Docker 安装环境检查Docker 安装 [ root 或者 sudo 权限用户可安装 ]给 普通用户 加入 Docker …

RedisConnectionException: Unable to connect to localhost/<unresolved>:6379

方法一&#xff1a;删除配置密码选项 一般是因为你在启动redsi服务的时候没有以指定配置文件启动 把application.yml文件中的redis密码注释掉 方法二 以指定配置文件启动 这样就不用删除yml文件中密码的选项了 在redis,windows.conf 中找到requirepass&#xff0c;删除掉前…

python 识别图片点击,设置坐标,离设置坐标越近的优先识别点击

import pyautogui import cv2 import numpy as np import mathdef find_and_click(template_path, target_x, target_y, match_threshold0.8):"""在屏幕上查找目标图片并点击。Args:template_path: 目标图片的路径。target_x: 预设的坐标 x 轴值。target_y: 预设…

ComfyUI中运行Stable Audio Open,实现背景音乐、音效自由

&#x1f9e8;背景 stability在一个月之前默默的发布了Stable Audio Open 1.0的音频音效生成模型&#xff0c;不过好像影响力一般&#xff0c;也没有太多文章分享测试&#xff0c;而今天看comfyui作者的一篇介绍文档&#xff0c;他已经让comfyui默认支持了这个模型。 原开源地…

学分制系统 WebService_PantoSchool SQL注入致RCE漏洞复现

0x01 产品简介 学分制系统由上海鹏达计算机系统开发有限公司研发,是基于对职业教育特点和需求的深入理解,结合教育部相关文件精神,并广泛吸纳专家、学者意见而开发的一款综合性管理系统。系统采用模块化的设计方法,方便学校根据自身教学改革特点、信息化建设进程情况选择、…

如何预防和处理他人盗用IP地址?

IP地址的定义及作用 解释 IP 地址在互联网中的作用。它是唯一标识网络设备的数字地址&#xff0c;类似于物理世界中的邮政地址。 1、IP地址盗窃的定义 解释一下什么是IP地址盗用&#xff0c;即非法使用他人的IP地址或者伪造IP地址的行为&#xff0c;这种行为可能引发法律和安…

uniapp 实人认证

最下面有demo 首先Dcloud创建云服务空间&#xff0c;开启一键登录并充值 下一步 1. 右键项目 》 创建uniCloud云开发环境 》右键uniCloud》关联云服务空间 2. cloudfunctions右键 新建云函数&#xff0c;任意命名&#xff08;例&#xff1a;veify&#xff09;&#xff0c;然…

elasticsearch重置密码

0 案例背景 Elasticsearch三台集群环境&#xff0c;对外端口为6200&#xff0c;忘记elasticsearch密码&#xff0c;进行重置操作 注&#xff1a;若无特殊说明&#xff0c;三台服务器均需进行处理操作 1 停止es /rpa/bin/elasticsearch.sh stop 检查状态 ps -ef|grep elast…

【Linux】ss 命令使用详解

目录 一、ss命令介绍 二、ss命令格式和使用 1、命令格式 2、ss命令的常用选项 3、命令的常见用法 3.1 找出打开套接字/端口应用程序 3.2 检查系统的监听套接字 3.3 显示所有状态为established的SMTP连接 3.4 查看建立的 TCP 连接 3.5 通过 -r 选项解析 IP 和端口号 …

UI(三)布局

文章目录 1、Colum和Row——垂直方向容器和水平方向容器2、ColumnSplit和RowSplit——子组件之间插入一条分割线3、Flex——弹性布局子组件的容器4、Grid和GridItem——网格容器和网格容器单元格5、GridRow和GridCol——栅格容器组件和栅格子组件6、List、ListItem、ListItemGr…