pytorch为自己的extension backend添加profiler功能

pytorch为自己的extension backend添加profiler功能

  • 1.参考文档
  • 2.your-extension-for-pytorch需要增加的代码
  • 3.pytorch demo及如何调整chrome trace json文件
  • 4.[可视化](https://ui.perfetto.dev/)

本文演示了pytorch如何为自己的extension backend添加profiler功能
背景介绍

  • 1.没有CNLight、Profiling AscendCL API、ROC Trace之类Profing功能,无法trace runtime,drive,kernel,也无法获取设备的metrics
  • 2.只有event功能,可以统计kernel耗时
  • 3.本文只是一种尝试,并不合理.
  • 4.torch原生的profiler框架,依赖kineto,kineto目前支持CUPTI和ROC Tracer,如果不修改torch源码,第三方设备不方便使用
  • 5.华为、寒武纪、habana都是采用torch.profile的接口形式及at::addThreadLocalCallback功能,但不依赖torch.profiler框架
    profing原始数据都是私有格式,并且修改TensorBoard的插件,可于可视化

实施步骤

  • 1.调用torch::profiler::impl::registerPrivateUse1Methods注册
  • 2.因为没有correlation ID去关联host api与kernel,因此export_chrome_trace出来的数据没有kernel信息
  • 3.获取prof.profiler.function_events里的数据,通过{ev.name}{ev.id}{ev.thread}拼成uuid与上面chrome trace中的events关联
  • 4.因为只有一个stream。可以根据Host lanuch时间、kernel耗时、launch latency(先验),推断出kernel的开始、结束时间,并用flow event进行关联(虽然并不准确)
  • 5.最后把kernel event以及flow event追加到chrome trace中

1.参考文档

  • ROC Tracer
  • CUPTI
  • 华为profiler_npu
  • Profiling AscendCL API
  • 寒武纪profile_mlu
  • 寒武纪CNLight
  • habana torch
  • intel_extension_for_pytorch
  • Make the kineto extendable for other runtime than CUD
  • pytorch_open_registration_example
  • rename_privateuse1_backend
  • Trace Event Format

2.your-extension-for-pytorch需要增加的代码

#include <torch/csrc/profiler/stubs/base.h>
#include <torch/csrc/profiler/util.h>
#include <c10/util/irange.h>
#include <torch/csrc/profiler/stubs/base.h>
#include <torch/csrc/profiler/util.h>using torch::profiler::impl::ProfilerStubs;
using torch::profiler::impl::ProfilerVoidEventStub;namespace torch {
namespace profiler {
namespace impl {struct NPUMethods : public ProfilerStubs {void record(int* device,ProfilerVoidEventStub* event,int64_t* cpu_ns) const override{if (device) {TORCH_CHECK(xpurtGetDevice((uint32_t*)device));}xpurtEvent_t xpurt_event;TORCH_CHECK(xpurtEventCreate(&xpurt_event));*event = std::shared_ptr<void>(xpurt_event, [](xpurtEvent_t ptr) {TORCH_CHECK(xpurtEventDestroy(ptr));});auto xpurt_stream = c10::xpu::getCurrentxpuStream(vastai::get_device());if (cpu_ns) {*cpu_ns = getTime();}TORCH_CHECK(xpurtEventRecord(xpurt_event, xpurt_stream)); } float elapsed(const ProfilerVoidEventStub* event1_,const ProfilerVoidEventStub* event2_) const override{auto event1 = static_cast<xpurtEvent_t>(event1_->get());TORCH_CHECK(xpurtEventSynchronize(event1));auto event2 = static_cast<xpurtEvent_t>(event2_->get());TORCH_CHECK(xpurtEventSynchronize(event2));int64_t time_ms = 0;TORCH_CHECK(xpurtEventElapsedTime(&time_ms, event1, event2));return time_ms*1.0;} void onEachDevice(std::function<void(int)> op) const override{uint32_t device = 0;TORCH_CHECK(xpurtGetDevice(&device));op(device);} void synchronize() const override { } bool enabled() const override {return true;} void mark(const char*name) const override { } void rangePush(const char*name) const override { } void rangePop() const override {}
};struct RegisterNPUMethods {RegisterNPUMethods(){static NPUMethods methods;torch::profiler::impl::registerPrivateUse1Methods(&methods);}
};
RegisterNPUMethods reg;
}}}

3.pytorch demo及如何调整chrome trace json文件

import time
import torchvision.models as models
from torch import nn
import torch.nn.functional as F
import copy
import math
import torch
from torch.profiler import profile
import json
import tqdmdef is_valid_kernel(name,duration,valid_kernel_threshold=100):'''通过算子的名字和耗时判断是否是Device Kernel'''invalid_kernels=["aten::view","aten::reshape","aten::t","aten::empty","aten::transpose","aten::as_strided","aten::item","aten::_local_scalar_dense","aten::result_type","aten::_unsafe_view","aten::expand"]for k in invalid_kernels:if name.find(k)>=0:return Falseif duration<valid_kernel_threshold:return False    return Truedef filter_ev(ev):'''过滤Kernel'''if 'args' in ev and "External id" in ev['args']:return Truereturn Falsedef get_uuid(ev,tid_map):return f"{ev['name']}_{ev['args']['External id']}_{tid_map[ev['tid']]}"def get_valid_kernels(traceEvents,kernel_event,tid_map):valid_kernels=[]device_memory_usage=0for ev in traceEvents:if filter_ev(ev):uuid=get_uuid(ev,tid_map)if uuid not in kernel_event:continueduration=kernel_event[uuid]['kernel_time']kernel_name=ev['name']if kernel_event[uuid]['device_memory_usage']>0:device_memory_usage=kernel_event[uuid]['device_memory_usage']if is_valid_kernel(kernel_name,duration):launch_beg=ev['ts']launch_end=ev['ts']+ev['dur']            valid_kernels.append({"name":kernel_name,"launch_beg":launch_beg,"launch_end":launch_end,"kernel_duration":duration,"host_pid":ev['pid'],"host_tid":ev['tid'],"device_memory_usage":device_memory_usage,"is_leaf_kernel":False})return sorted(valid_kernels,key=lambda x:x['launch_beg'])def is_leaf_kernel(kernel,valid_kernels):'''判断是否是叶子Kernel'''ret=Truefor k in valid_kernels:if k['is_leaf_kernel']:continue#自己的时间跨度内还有别的Kernelif k['launch_beg']>kernel['launch_beg'] and k['launch_end']<kernel['launch_end']:ret=Falsebreakreturn retdef create_tid_map(traceEvents):tids=set()for ev in traceEvents:if filter_ev(ev):tid=ev['tid']tids.add(tid)tid_map={}tids=sorted(tids,reverse=False)for i,v in enumerate(tids):tid_map[v]=i+1return tid_mapdef merge_prof_timeline(prof_json,kernel_event_json,output_json):kernel_lanuch_latency=0with open(prof_json,'r',encoding='utf-8') as f:prof = json.load(f)with open(kernel_event_json,'r',encoding='utf-8') as f:kernel_event = json.load(f)   traceEvents=prof['traceEvents']tid_map=create_tid_map(traceEvents)print(tid_map)#获取所有kernelvalid_kernels=get_valid_kernels(traceEvents,kernel_event,tid_map)print(len(valid_kernels))#筛出所有会在device上执行的kernelon_device_kernels=[]for kernel in tqdm.tqdm(valid_kernels):if is_leaf_kernel(kernel,valid_kernels):on_device_kernels.append(kernel)kernel_start_offset=0kernel_index=0for kernel in on_device_kernels:name=kernel['name']kernel_duration=kernel["kernel_duration"]lanuch_time=kernel["launch_beg"]host_pid=kernel['host_pid']host_tid=kernel['host_tid']device_memory_usage=kernel['device_memory_usage']if kernel_start_offset==0:kernel_start_offset=lanuch_time+kernel_start_offsetif lanuch_time>kernel_start_offset: #kernel 队列空闲kernel_start_offset=lanuch_time#增加kernel事件traceEvents.append({"ph": "X", "cat": "device_kernel", "name":name, "pid": 10, "tid": 10,"ts": kernel_start_offset, "dur": kernel_duration})#增加内存事件traceEvents.append({"ph": "C", "cat": "memory", "name":"memory", "pid": 11, "tid": 11,"ts": lanuch_time, "args": {"value":device_memory_usage}})#增加flow eventtraceEvents.append({"ph": "s", "id": kernel_index, "pid": host_pid, "tid": host_tid, "ts": lanuch_time,"cat": "ac2g", "name": "ac2g"})traceEvents.append({"ph": "f", "id": kernel_index, "pid": 10,  "tid": 10,"ts": kernel_start_offset,"cat": "ac2g", "name": "ac2g", "bp": "e"})kernel_index+=1kernel_start_offset+=(kernel_duration+kernel_lanuch_latency)#保存最终的结果with open(output_json,'w',encoding='utf-8') as f:json.dump(prof, f,ensure_ascii=False,indent=4)def clones(module, N):return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])class ScaledDotProductAttention(nn.Module):def __init__(self):super(ScaledDotProductAttention, self).__init__()def forward(self,query, key, value, mask=None, dropout=None):d_k = query.size(-1)scores = query@key.transpose(-2,-1) / math.sqrt(d_k)if mask is not None:scores = scores.masked_fill(mask == 0, -1e20)p_attn = F.softmax(scores, dim = -1)if dropout is not None:p_attn = dropout(p_attn)return p_attn@value, p_attnclass MultiHeadAttention(nn.Module):def __init__(self, h, d_model, dropout=0.1):super(MultiHeadAttention, self).__init__()assert d_model % h == 0self.d_k = d_model // hself.h = hself.linears = clones(nn.Linear(d_model, d_model), 4)self.attn = Noneself.dropout = nn.Dropout(p=dropout)self.attention = ScaledDotProductAttention()def forward(self, query, key, value, mask=None):if mask is not None:mask = mask.unsqueeze(1)nbatches = query.size(0)query=self.linears[0](query).view(nbatches, -1, self.h, self.d_k)query=query.transpose(1, 2)key=self.linears[1](key).view(nbatches, -1, self.h, self.d_k)key=key.transpose(1, 2)value=self.linears[2](value).view(nbatches, -1, self.h, self.d_k).transpose(1, 2)x, self.attn = self.attention(query, key, value, mask=mask,dropout=self.dropout)x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.h * self.d_k)return self.linears[-1](x)use_cuda=True
try:import torch_xpuimport torch_xpu.contrib.transfer_to_xputorch.xpu.set_device(0)torch.profiler.ProfilerActivity.PrivateUse1="xpu"use_cuda=False
except:passimport os
os.environ['LOCAL_RANK']="0"
os.environ['RANK']="0"
os.environ['WORLD_SIZE']="1"
os.environ['MASTER_ADDR']="localhost"
os.environ['MASTER_PORT']="6006"import torch.distributed as dist
dist.init_process_group(backend='vccl')
local_rank=int(os.environ['LOCAL_RANK'])
rank=torch.distributed.get_rank()
torch.cuda.set_device(local_rank)
if not dist.is_available() or not dist.is_initialized():print("dist init error")cross_attn = MultiHeadAttention(h=8, d_model=64).half().cuda()
cross_attn.eval()
q1 = torch.ones((1, 50, 64),dtype=torch.float32).half().cuda()
k1 = q1.clone()
v1 = q1.clone()
out = cross_attn.forward(q1,k1,v1).sum()
torch.cuda.synchronize()activities=[torch.profiler.ProfilerActivity.CPU]
if use_cuda:activities.append(torch.profiler.ProfilerActivity.CUDA)with profile(activities=activities,schedule=torch.profiler.schedule(wait=1,warmup=1,active=3,repeat=1),record_shapes=True,with_stack=True,with_modules=True,with_flops=True,profile_memory=True,) as prof:for i in range(10):out = cross_attn.forward(q1,k1,v1).sum()prof.step()torch.cuda.synchronize()if not use_cuda:kernel_event={}for ev in prof.profiler.function_events:if ev.privateuse1_time>0:uuid=f"{ev.name}_{ev.id}_{ev.thread}"#print(uuid,ev.id,ev.name,ev.privateuse1_time,ev.time_range.start,ev.time_range.end-ev.time_range.start,ev.privateuse1_memory_usage)kernel_event[uuid]={"kernel_time":ev.privateuse1_time,"device_memory_usage":ev.privateuse1_memory_usage,"start_us":ev.time_range.start,"host_dur":ev.time_range.end-ev.time_range.start,"thread":ev.thread} import jsonwith open(f"kernel_event_{rank}.json",'w',encoding='utf-8') as f:json.dump(kernel_event, f,ensure_ascii=False,indent=4)prof.export_chrome_trace(f"prof_{rank}.json")merge_prof_timeline(f"prof_{rank}.json",f"kernel_event_{rank}.json",f"prof_{rank}.json")
else:#print(prof.key_averages().table(sort_by="self_cpu_time_total"))prof.export_chrome_trace(f"prof_{q1.device.type}.json")

4.可视化

在这里插入图片描述

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

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

相关文章

Taro +vue3 中的微信小程序中的分享

微信小程序 右上角分享 的触发 以及配 useShareAppMessage(() > {return {title: "电影属全国通兑券",page: /pages/home/index,imageUrl: "http:///chuanshuo.jpg",};}); 置 就是Taro框架中提供的一个分享Api 封装好的

项目经理必读:三步走实现项目高效管理

一个项目的成功往往取决于项目管理能力的高低。若管理不当&#xff0c;易导致团队成员间的推诿和抱怨&#xff0c;且项目团队还可能面临成员对目标不明确、信息不透明、进度难以跟踪等问题。作为项目经理&#xff0c;掌握有效的项目管理策略至关重要。 一、精细化的目标拆解 …

数据库逻辑结构设计-实体和实体间联系的转换、关系模式的优化

一、引言 如何将数据库概念结构设计的结果&#xff0c;即用E-R模型表示的概念模型转化为关系数据库模式。 E-R模型由实体、属性以及实体间的联系三个要素组成 将E-R模型转换为关系数据库模式&#xff0c;实际上就是要将实体及实体联系转换为相应的关系模式&#xff0c;转换…

【EtherCAT】TwinCAT3通过PLC修改SDO数据

目录 1、打开twincat3, 左边PLC右键->添加新项&#xff0c;建立PLC工程 2、->References右键添加库 3、找到Tc2_EtherCAT库&#xff0c;点确定。 4、PLC程序ST语言就可以调用下面的功能块函数 5、PLC编程界面右键->输入助手 1、打开twincat3, 左边PLC右键->添…

数据恢复篇:如何恢复丢失的Android短信?

许多用户发现自己处于重要短信意外从Android手机中删除的情况。幸运的是&#xff0c;有一些行之有效的方法可以在没有root的情况下恢复已删除的短信Android&#xff0c;这可以成为救命稻草。这些技术不需要深厚的技术知识&#xff0c;也不需要损害设备的安全性。为了帮助您摆脱…

jieba--《红楼梦》章节分卷并计算TF-IDF值(超详细)

目录 大致步骤&#xff1a; 任务1&#xff1a; 将红楼梦 根据卷名 分隔成 卷文件 红楼梦txt&#xff1a; 红楼梦卷头&#xff1a; 红楼梦章节分卷&#xff1a; 任务2&#xff1a;对每个卷进行分词&#xff0c;并删除包含停用词的内容 1.遍历所有卷的内容&#xff0c;并添…

Python26 Lambda表达式

1.什么是lambda表达式 lambda 是 Python 中的一个关键字&#xff0c;用于定义简单的匿名函数。与 def 关键字定义的标准函数不同&#xff0c;lambda 函数主要用于需要一个函数对象作为参数的简短操作。lambda 函数的设计哲学是简洁&#xff0c;因此它只能包含一条表达式&#…

7km远距离WiFi实时图传模块,无人机海上无线传输方案,飞睿智能WiFi MESH自组网技术

在浩瀚无垠的海洋上&#xff0c;无人机正在开启一场前所未有的技术创新。它们不再只是天空的舞者&#xff0c;更是海洋的守望者&#xff0c;为我们带来前所未有的视野和数据。而这一切的背后&#xff0c;都离不开一项创新性的技术——飞睿智能远距离WiFi实时图传模块与无线Mesh…

java必知必会-java IO

系列文章目录 java必知必会-java环境搭建 java必知必会-java开发工具安装与使用 java必知必会-java关键字、变量和常量 java必知必会-java数据类型和变量定义 java必知必会-java类和对象 java必知必会-java面向对象的三大特性 java必知必会-java继承与重写、重载 java必知必会…

昇思25天学习打卡营第1天|快速入门-Mnist手写数字识别

学习目标&#xff1a;熟练掌握MindSpore使用方法 学习心得体会&#xff0c;记录时间 了解MindSpore总体架构 学会使用MindSpore 简单应用时间-手写数字识别 一、MindSpore总体架构 华为MindSpore为全场景深度学习框架&#xff0c;开发高效&#xff0c;全场景统一部署特点。 …

Verilog进行结构描述(三):Verilog模块实例化

目录 1.模块实例化(module instantiation)2.实例数组(Array of Instances) 微信公众号获取更多FPGA相关源码&#xff1a; 1.模块实例化(module instantiation) 模块实例化时实例必须有一个名字。使用位置映射时&#xff0c;端口次序与模块的说明相同。使用名称映射时&#x…

搭建大型分布式服务(四十)SpringBoot 整合多个kafka数据源-支持生产者

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目&#xff0c;每天处理上亿级的数据的精简小插件&#xff0c;快速上手。 <dependency><groupId>io.github.vipjo…

ZYNQ学习教程?ZYNQ-FPGA实战教程!

学习 ZYNQ 比FPGA、MCU、ARM 等传统工具开发要求更高&#xff0c;想学好 ZYNQ 也不是一蹴而就的事情。 学习 ZYNQ 要具备的技能&#xff1a; 1、 软件开发人员  计算机组成原理、 C、C语言、 计算机操作系统、tcl 脚本、良好的英语基础 2、 逻辑开发人员 计算机组成原理…

关于服务器的一些知识

1. 云服务器 和 轻量应用服务器 腾讯云中的"云服务器"&#xff08;Cloud Virtual Machine, CVM&#xff09;和"轻量应用服务器"&#xff08;Lite Cloud Server&#xff09;都是提供云端计算资源的服务&#xff0c;但它们在定位、特性和使用场景上存在一些差…

LongRAG:利用长上下文大语言模型提升检索生成效果

一、前言 前面我们已经介绍了多种检索增强生成 (RAG) 技术&#xff0c;基本上在保证数据质量的前提下&#xff0c;检索增强生成&#xff08;RAG&#xff09;技术能够有效提高检索效率和质量&#xff0c;相对于大模型微调技术&#xff0c;其最大的短板还是在于有限的上下文窗口…

幽默证明题!高考成绩公布后,妈妈连夜写了一封信:孩子,这就是我不让你玩手机的原因——早读(逆天打工人爬取热门微信文章解读)

毛毛雨&#xff0c;五分钟结束&#xff0c;怎么证明今天早上有下雨呢&#xff1f; 引言Python 代码第一篇 洞见 高考成绩公布后&#xff0c;妈妈连夜写了一封信&#xff1a;孩子&#xff0c;这就是我不让你玩手机的原因第二篇 视频新闻结尾 引言 今天睡眠质量不错 发现一个问题…

10分钟微调专属于自己的大模型_10分钟微调大模型

1.环境安装 # 设置pip全局镜像 (加速下载) pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # 安装ms-swift pip install ms-swift[llm] -U# 环境对齐 (通常不需要运行. 如果你运行错误, 可以跑下面的代码, 仓库使用最新环境测试) pip install -r r…

vb6多线程异步,VB.NET 全用API实现:CreateThread创建多线程,等待线程完成任务

在VB.NET中&#xff0c;你可以使用API函数来创建多线程并等待线程完成任务。以下是一个示例代码&#xff0c;展示如何使用API函数来实现这个功能&#xff1a; Imports System.Runtime.InteropServices Imports System.ThreadingPublic Class Form1Private Delegate Sub ThreadC…

大模型+多模态合规分析平台,筑牢金融服务安全屏障

随着金融市场的快速发展&#xff0c;金融产品和服务日趋多样化&#xff0c;消费者面临的风险也逐渐增加。 为保护消费者权益&#xff0c;促进金融市场长期健康稳定发展&#xff0c;国家监管机构不断加强金融监管&#xff0c;出台了一系列法律法规和政策文件。对于金融从业机构…

【DC-DC升压电推剪方案】FP6277,FP6296电源升压芯片在电推剪中扮演着一个怎样的角色?带你深入了解电推剪的功能和应用及工作原理

随着人们对个人形象要求的不断提高&#xff0c;理发器作为一个必备的家居用品&#xff0c;也在不断进行技术升级。而其中的核心装备之一&#xff0c;电推剪理发器升压芯片FP6277、FP6296&#xff0c;正在引领着现代理发技术的突破。本文将给大家带来的是电推剪在传统意义上运用…