用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.mzph.cn/diannao/36518.shtml

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

相关文章

【银河麒麟】unzip程序卡住,处理机制详解,附代码

1.服务器环境以及配置 【机型】 处理器&#xff1a; HUAWEI,Kunpeng 920 内存&#xff1a; 400G 【内核版本】 4.19.90-23.18.v2101.ky10.aarch64 【OS镜像版本】 银河麒麟高级服务器操作系统V10-SP1-0711-arm 【第三方软件】 docker 2.问题现象描述 一台k8s服务器…

水上实用救生工具_救生拉杆_鼎跃安全

每年&#xff0c;由于水上事故而失去生命的人数不胜数&#xff0c;水上安全问题也成为公众关注的焦点。如何在关键时刻实施有效的救援&#xff0c;成为保障生命的重要课题。作为水上救援的重要工具&#xff0c;救生拉杆在紧急情况下发挥了无可替代的作用。 救生拉杆&#xff0c…

springboot 缓存框架Cache整合redis组成二级缓存

springboot 缓存框架Cache整合redis组成二级缓存 项目性能优化的解决方案除开硬件外的方案无非就是优化sql&#xff0c;减少sql 的执行时间&#xff0c;合理运用缓存让同样的请求和数据库之间的连接尽量减少&#xff0c;内存的处理速度肯定比直接查询数据库来的要快一些。今天就…

CDP问卷的常见问题

CDP问卷的常见问题可以归纳如下&#xff1a; 哪些企业会收到CDP邀请&#xff1f; 企业会收到来自投资和/或采购机构的邀请&#xff0c;以填写CDP问卷并披露相应的环境管理信息。 未收到邀请的企业可否填报&#xff1f; 未收到邀请的企业可以选择自行填报。他们需发送申请自愿…

多线程(基础)

前言&#x1f440;~ 上一章我们介绍了什么是进程&#xff0c;对于进程就了解那么多即可&#xff0c;我们作为java程序员更关注线程&#xff0c;线程内容比较多&#xff0c;所以我们要分好几部分才能讲完 目录 进程的缺点 多线程&#xff08;重要&#xff09; 进程和线程的区…

鸿蒙开发Ability Kit(程序框架服务):【FA模型切换Stage模型指导】 module的切换

module的切换 从FA模型切换到Stage模型时&#xff0c;开发者需要将config.json文件module标签下的配置迁移到module.json5配置文件module标签下&#xff0c;具体差异见下列表格。 表1 FA模型module标签与Stage模型module标签差异对比 FA标签标签说明对应的Stage标签差异说明…

LeetCode刷题之HOT100之课程表

吃完普通的食堂饭菜&#xff0c;回到实验室&#xff0c;继续做一道题&#xff01; 1、题目描述 2、逻辑分析 这道题涉及到图相关知识&#xff0c;应用到了拓扑排序。 题意解释 一共有 n 门课要上&#xff0c;编号为 0 ~ n-1。先决条件 [1, 0]&#xff0c;意思是必须先上课 0…

触动心弦的成语之旅:《米小圈动画成语》带你走进中华智慧

成语&#xff0c;这些古老而典雅的语言精华&#xff0c;如同中华文化的晶莹明珠&#xff0c;闪耀着历史的光辉和智慧的火花。从古至今&#xff0c;它们在中国人的日常交流中扮演着重要角色&#xff0c;不仅传递着深刻的哲理和文化内涵&#xff0c;更是凝聚了世代智者的思想和智…

【Linux】线程id与互斥(线程三)

上一期我们进行了线程控制的了解与相关操作&#xff0c;但是扔就有一些问题没有解决 本章第一阶段就是解决tid的问题&#xff0c;第二阶段是进行模拟一个简易线程库&#xff08;为了加深对于C库封装linux原生线程的理解&#xff09;&#xff0c;第三阶段就是互斥。 目录 线程id…

链在一起怎么联机 链在一起远程同玩联机教程

steam中最近特别热门的多人跑酷冒险的游戏&#xff1a;《链在一起》&#xff0c;英文名称叫做Chained Together&#xff0c;在游戏中我们需要开始自己的旅程&#xff0c;在地狱的深处&#xff0c;与我们的同伴被链在一起。我们的任务是通过尽可能高的攀登逃离地狱。每一次跳跃都…

Python第三方库GDAL 安装

安装GDAL的方式多种&#xff0c;包括pip、Anaconda、OSGeo4W等。笔者在安装过程中&#xff0c;唯独使用pip安装遇到问题。最终通过轮子文件&#xff08;.whl&#xff09;成功安装。 本文主要介绍如何下载和安装较新版本的GDAL轮子文件。 一、GDAL轮子文件下载 打开Github网站…

Python学习打卡:day16

day16 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day16116、SQL 基础和 DDLSQL的概述SQL语言的分类SQL的语法特征DDL — 库管理DDL — 表管理 117、SQL — DMLDML概述数据插入 INSERT数据删除 DEL…

深入理解 Dubbo:分布式服务框架的核心原理与实践

目录 Dubbo 概述Dubbo 的架构Dubbo 的关键组件 服务提供者&#xff08;Provider&#xff09;服务消费者&#xff08;Consumer&#xff09;注册中心&#xff08;Registry&#xff09;监控中心&#xff08;Monitor&#xff09;调用链追踪&#xff08;Trace&#xff09; Dubbo 的…

专题页面设计指南:从构思到实现

如何设计专题页&#xff1f;你有什么想法&#xff1f;专题页的设计主要以发扬产品优势为核心。一个好的专题页可以从不同的角度向用户介绍产品&#xff0c;扩大产品的相关优势&#xff0c;表达产品的优势&#xff0c;让用户在短时间内了解产品。因此&#xff0c;在设计详细信息…

纯血鸿蒙Beta版本发布,中国华为,站起来了!

2024年6月21日至23日&#xff0c;华为开发者大会2024&#xff08;HDC 2024&#xff09;于东莞盛大举行。 此次大会不仅在会场设置了包括鸿蒙原生应用、统一生态统一互联等在内的11个展区&#xff0c;以供展示HarmonyOS NEXT的强大实力&#xff0c;还对外宣布了HarmonyOS的最新进…

240627_关于CNN中图像维度变化问题

240627_关于CNN中图像维度变化问题 在学习一些经典模型时&#xff0c;其中得维度变化关系总搞不太明白&#xff0c;集中学习了以下&#xff0c;在此作以梳理总结&#xff1a; 一般来说涉及到的维度变换都是四个维度&#xff0c;当batch size4&#xff0c;图像尺寸为640*640&a…

kylin v10 离线安装chrome centos离线安装chrome linux离线安装谷歌浏览器

1. 先用自己联网的计算机&#xff0c;下载离线安装包&#xff0c;浏览器输入链接下载安装包&#xff1a; https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 1.2. 信创环境不用执行下面&#xff0c;因为没网 1.3. 若为阿里云服务器&#xff0c;或服…

AR导航技术加持,图书馆阅读体验智慧升级

在信息爆炸的今天&#xff0c;图书馆作为知识的宝库&#xff0c;其藏书量和种类日益增多。然而&#xff0c;传统的图书馆导航方式已逐渐无法满足用户对快速、准确定位图书的需求。本文将探讨图书馆AR地图导航的实现原理、技术优势、功能特点以及市场前景&#xff0c;揭示为何AR…

VS studio2019配置远程连接Ubuntu

VS studio2019配置远程连接Ubuntu 1、网络配置 &#xff08;1&#xff09;获取主机IP &#xff08;2&#xff09;获取Ubuntu的IP &#xff08;3&#xff09;在 windows 的控制台中 ping 虚拟机的 ipv4 地址&#xff0c;在 Ubuntu 中 ping 主机的 ipv4 地址。 ubuntu: ping…

【Linux】对共享库加载问题的深入理解——基本原理概述

原理概述 【linux】详解——库-CSDN博客 共享库被加载后&#xff0c;系统会为该共享库创建一个结构&#xff0c;这个结构体中的字段描述了库的各种属性。在内存中可能会加载很多库&#xff0c;每一个库都用一个结构体描述。把这些结构体用一些数据结构管理起来&#xff0c;系…