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 封装好的

Tailwind CSS 在vue里 的使用

Tailwind CSS 在vue里 的使用 安装 npm install -D tailwindcsslatest postcsslatest autoprefixerlatest创建您的配置文件 生成您的 tailwind.config.js 和 postcss.config.js 文件&#xff1a; npx tailwindcss init -p您的项目根目录创建一个最小化的 tailwind.config.js…

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

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

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

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

模板特化的作用是什么

模板特化的作用是在某种特定类型下为模板提供具体的实现&#xff0c;以解决通用模板在某些特殊类型下无法满足特定需求的问题。模板特化分为全特化和偏特化两种形式。 1. 全特化&#xff08;全具体化&#xff09; 定义&#xff1a;全特化是当模板的所有模板参数都明确指定了具…

「树莓派入门」树莓派基础03-DRP远程连接控制树莓派(无线网络连接)

一、无线网络连接配置 1. 确认无线网络设备状态 使用 iwconfig 命令来查看无线网络接口的状态。 iwconfig2. 扫描无线网络 使用 iwlist 命令扫描可用的无线网络。 sudo iwlist wlan0 scan3. 配置无线网络连接 创建或编辑 wpa_supplicant.conf 文件&#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;也不需要损害设备的安全性。为了帮助您摆脱…

DDei在线设计器-API-DDeiAbstractShape

DDeiAbstractShape DDeiAbstractShape代表是所有可见图形的父类&#xff0c;定义了图形所需要的公共属性和方法。   DDeiAbstractShape实例包含了一个图形的所有数据和渲染器&#xff0c;在获取后可以通过它访问其他内容。DDeiAbstractShape中的layer指向所在图层,stage指向所…

使用 Node.js 发送电子邮件

前言&#xff1a;大多数 Web 应用程序都需要发送电子邮件。它可能用于注册、密码重置、状态报告&#xff0c;甚至是完整的营销活动&#xff08;例如新闻通讯和促销&#xff09;。本教程介绍如何在 Node.js 中发送电子邮件&#xff0c;但这些概念和挑战适用于您使用的任何系统。…

Spring Boot与JMS消息中间件的集成

Spring Boot与JMS消息中间件的集成 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨一下如何在Spring Boot中集成JMS&#xff08;Java Message Se…

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…

使用Spring Boot和WebSocket实现实时通信

使用Spring Boot和WebSocket实现实时通信 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot应用中使用WebSocket实现实时通信&am…

【杂记-浅谈CHAP认证(质询握手身份验证协议)】

CHAP认证&#xff08;质询握手身份验证协议&#xff09; 一、CHAP认证概述二、CHAP认证流程三、CHAP认证优势 一、CHAP认证概述 1、CHAP&#xff0c;Challenge Handshake Authentication Protocol&#xff0c;即质询握手身份验证协议&#xff0c;是一种用于网络连接的验证协议…

JavaScript数组forEach方法退出循环

常规for循环退出循环方法 在for循环中退出循环有3种方式&#xff1a;return&#xff08;终止&#xff09;、break&#xff08;退出整个循环&#xff09;、continue&#xff08;退出当次循环&#xff09;。 let arr [0,1,2,3,4,5,6] for(let i0;i<array.length;i){if(array[…

并发业务使用redis分布式锁

伴随着业务体量的上升&#xff0c;我们的qps与并发问题越来越明显&#xff0c;这时候就需要用到让代码一定情况下进行串行执行的工具&#xff1a;锁 1.业务场景代码 OverrideTransactional(rollbackFor Exception.class)public Object testBatch(User user) {LambdaQueryWrapp…

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;全场景统一部署特点。 …