René's URL Explorer Experiment


Title: (beta) Building a Simple CPU Performance Profiler with FX — 파이토치 한국어 튜토리얼 (PyTorch tutorials in Korean)

Open Graph Title: (beta) Building a Simple CPU Performance Profiler with FX

Description: Author: James Reed In this tutorial, we are going to use FX to do the following: Capture PyTorch Python code in a way that we can inspect and gather statistics about the structure and execution of the code, Build out a small class that will serve as a simple performance “profiler”, collecting run...

Open Graph Description: Author: James Reed In this tutorial, we are going to use FX to do the following: Capture PyTorch Python code in a way that we can inspect and gather statistics about the structure and execution of the code, Build out a small class that will serve as a simple performance “profiler”, collecting run...

Opengraph URL: https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html

direct link

Domain: tutorials.pytorch.kr


Hey, it has json ld scripts:
    {
       "@context": "https://schema.org",
       "@type": "Article",
       "name": "(beta) Building a Simple CPU Performance Profiler with FX",
       "headline": "(beta) Building a Simple CPU Performance Profiler with FX",
       "description": "PyTorch Documentation. Explore PyTorch, an open-source machine learning library that accelerates the path from research prototyping to production deployment. Discover tutorials, API references, and guides to help you build and deploy deep learning models efficiently.",
       "url": "/intermediate/fx_profiling_tutorial.html",
       "articleBody": "\ucc38\uace0 Go to the end to download the full example code. (beta) Building a Simple CPU Performance Profiler with FX# Author: James Reed In this tutorial, we are going to use FX to do the following: Capture PyTorch Python code in a way that we can inspect and gather statistics about the structure and execution of the code Build out a small class that will serve as a simple performance \u201cprofiler\u201d, collecting runtime statistics about each part of the model from actual runs. For this tutorial, we are going to use the torchvision ResNet18 model for demonstration purposes. import torch import torch.fx import torchvision.models as models rn18 = models.resnet18() rn18.eval() ResNet( (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) (layer1): Sequential( (0): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) (1): BasicBlock( (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (layer2): Sequential( (0): BasicBlock( (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (layer3): Sequential( (0): BasicBlock( (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (layer4): Sequential( (0): BasicBlock( (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (downsample): Sequential( (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False) (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (1): BasicBlock( (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) (avgpool): AdaptiveAvgPool2d(output_size=(1, 1)) (fc): Linear(in_features=512, out_features=1000, bias=True) ) Now that we have our model, we want to inspect deeper into its performance. That is, for the following invocation, which parts of the model are taking the longest? input = torch.randn(5, 3, 224, 224) output = rn18(input) A common way of answering that question is to go through the program source, add code that collects timestamps at various points in the program, and compare the difference between those timestamps to see how long the regions between the timestamps take. That technique is certainly applicable to PyTorch code, however it would be nicer if we didn\u2019t have to copy over model code and edit it, especially code we haven\u2019t written (like this torchvision model). Instead, we are going to use FX to automate this \u201cinstrumentation\u201d process without needing to modify any source. First, let\u2019s get some imports out of the way (we will be using all of these later in the code). import statistics, tabulate, time from typing import Any, Dict, List from torch.fx import Interpreter \ucc38\uace0 tabulate is an external library that is not a dependency of PyTorch. We will be using it to more easily visualize performance data. Please make sure you\u2019ve installed it from your favorite Python package source. Capturing the Model with Symbolic Tracing# Next, we are going to use FX\u2019s symbolic tracing mechanism to capture the definition of our model in a data structure we can manipulate and examine. traced_rn18 = torch.fx.symbolic_trace(rn18) print(traced_rn18.graph) graph(): %x : torch.Tensor [num_users=1] = placeholder[target=x] %conv1 : [num_users=1] = call_module[target=conv1](args = (%x,), kwargs = {}) %bn1 : [num_users=1] = call_module[target=bn1](args = (%conv1,), kwargs = {}) %relu : [num_users=1] = call_module[target=relu](args = (%bn1,), kwargs = {}) %maxpool : [num_users=2] = call_module[target=maxpool](args = (%relu,), kwargs = {}) %layer1_0_conv1 : [num_users=1] = call_module[target=layer1.0.conv1](args = (%maxpool,), kwargs = {}) %layer1_0_bn1 : [num_users=1] = call_module[target=layer1.0.bn1](args = (%layer1_0_conv1,), kwargs = {}) %layer1_0_relu : [num_users=1] = call_module[target=layer1.0.relu](args = (%layer1_0_bn1,), kwargs = {}) %layer1_0_conv2 : [num_users=1] = call_module[target=layer1.0.conv2](args = (%layer1_0_relu,), kwargs = {}) %layer1_0_bn2 : [num_users=1] = call_module[target=layer1.0.bn2](args = (%layer1_0_conv2,), kwargs = {}) %add : [num_users=1] = call_function[target=operator.add](args = (%layer1_0_bn2, %maxpool), kwargs = {}) %layer1_0_relu_1 : [num_users=2] = call_module[target=layer1.0.relu](args = (%add,), kwargs = {}) %layer1_1_conv1 : [num_users=1] = call_module[target=layer1.1.conv1](args = (%layer1_0_relu_1,), kwargs = {}) %layer1_1_bn1 : [num_users=1] = call_module[target=layer1.1.bn1](args = (%layer1_1_conv1,), kwargs = {}) %layer1_1_relu : [num_users=1] = call_module[target=layer1.1.relu](args = (%layer1_1_bn1,), kwargs = {}) %layer1_1_conv2 : [num_users=1] = call_module[target=layer1.1.conv2](args = (%layer1_1_relu,), kwargs = {}) %layer1_1_bn2 : [num_users=1] = call_module[target=layer1.1.bn2](args = (%layer1_1_conv2,), kwargs = {}) %add_1 : [num_users=1] = call_function[target=operator.add](args = (%layer1_1_bn2, %layer1_0_relu_1), kwargs = {}) %layer1_1_relu_1 : [num_users=2] = call_module[target=layer1.1.relu](args = (%add_1,), kwargs = {}) %layer2_0_conv1 : [num_users=1] = call_module[target=layer2.0.conv1](args = (%layer1_1_relu_1,), kwargs = {}) %layer2_0_bn1 : [num_users=1] = call_module[target=layer2.0.bn1](args = (%layer2_0_conv1,), kwargs = {}) %layer2_0_relu : [num_users=1] = call_module[target=layer2.0.relu](args = (%layer2_0_bn1,), kwargs = {}) %layer2_0_conv2 : [num_users=1] = call_module[target=layer2.0.conv2](args = (%layer2_0_relu,), kwargs = {}) %layer2_0_bn2 : [num_users=1] = call_module[target=layer2.0.bn2](args = (%layer2_0_conv2,), kwargs = {}) %layer2_0_downsample_0 : [num_users=1] = call_module[target=layer2.0.downsample.0](args = (%layer1_1_relu_1,), kwargs = {}) %layer2_0_downsample_1 : [num_users=1] = call_module[target=layer2.0.downsample.1](args = (%layer2_0_downsample_0,), kwargs = {}) %add_2 : [num_users=1] = call_function[target=operator.add](args = (%layer2_0_bn2, %layer2_0_downsample_1), kwargs = {}) %layer2_0_relu_1 : [num_users=2] = call_module[target=layer2.0.relu](args = (%add_2,), kwargs = {}) %layer2_1_conv1 : [num_users=1] = call_module[target=layer2.1.conv1](args = (%layer2_0_relu_1,), kwargs = {}) %layer2_1_bn1 : [num_users=1] = call_module[target=layer2.1.bn1](args = (%layer2_1_conv1,), kwargs = {}) %layer2_1_relu : [num_users=1] = call_module[target=layer2.1.relu](args = (%layer2_1_bn1,), kwargs = {}) %layer2_1_conv2 : [num_users=1] = call_module[target=layer2.1.conv2](args = (%layer2_1_relu,), kwargs = {}) %layer2_1_bn2 : [num_users=1] = call_module[target=layer2.1.bn2](args = (%layer2_1_conv2,), kwargs = {}) %add_3 : [num_users=1] = call_function[target=operator.add](args = (%layer2_1_bn2, %layer2_0_relu_1), kwargs = {}) %layer2_1_relu_1 : [num_users=2] = call_module[target=layer2.1.relu](args = (%add_3,), kwargs = {}) %layer3_0_conv1 : [num_users=1] = call_module[target=layer3.0.conv1](args = (%layer2_1_relu_1,), kwargs = {}) %layer3_0_bn1 : [num_users=1] = call_module[target=layer3.0.bn1](args = (%layer3_0_conv1,), kwargs = {}) %layer3_0_relu : [num_users=1] = call_module[target=layer3.0.relu](args = (%layer3_0_bn1,), kwargs = {}) %layer3_0_conv2 : [num_users=1] = call_module[target=layer3.0.conv2](args = (%layer3_0_relu,), kwargs = {}) %layer3_0_bn2 : [num_users=1] = call_module[target=layer3.0.bn2](args = (%layer3_0_conv2,), kwargs = {}) %layer3_0_downsample_0 : [num_users=1] = call_module[target=layer3.0.downsample.0](args = (%layer2_1_relu_1,), kwargs = {}) %layer3_0_downsample_1 : [num_users=1] = call_module[target=layer3.0.downsample.1](args = (%layer3_0_downsample_0,), kwargs = {}) %add_4 : [num_users=1] = call_function[target=operator.add](args = (%layer3_0_bn2, %layer3_0_downsample_1), kwargs = {}) %layer3_0_relu_1 : [num_users=2] = call_module[target=layer3.0.relu](args = (%add_4,), kwargs = {}) %layer3_1_conv1 : [num_users=1] = call_module[target=layer3.1.conv1](args = (%layer3_0_relu_1,), kwargs = {}) %layer3_1_bn1 : [num_users=1] = call_module[target=layer3.1.bn1](args = (%layer3_1_conv1,), kwargs = {}) %layer3_1_relu : [num_users=1] = call_module[target=layer3.1.relu](args = (%layer3_1_bn1,), kwargs = {}) %layer3_1_conv2 : [num_users=1] = call_module[target=layer3.1.conv2](args = (%layer3_1_relu,), kwargs = {}) %layer3_1_bn2 : [num_users=1] = call_module[target=layer3.1.bn2](args = (%layer3_1_conv2,), kwargs = {}) %add_5 : [num_users=1] = call_function[target=operator.add](args = (%layer3_1_bn2, %layer3_0_relu_1), kwargs = {}) %layer3_1_relu_1 : [num_users=2] = call_module[target=layer3.1.relu](args = (%add_5,), kwargs = {}) %layer4_0_conv1 : [num_users=1] = call_module[target=layer4.0.conv1](args = (%layer3_1_relu_1,), kwargs = {}) %layer4_0_bn1 : [num_users=1] = call_module[target=layer4.0.bn1](args = (%layer4_0_conv1,), kwargs = {}) %layer4_0_relu : [num_users=1] = call_module[target=layer4.0.relu](args = (%layer4_0_bn1,), kwargs = {}) %layer4_0_conv2 : [num_users=1] = call_module[target=layer4.0.conv2](args = (%layer4_0_relu,), kwargs = {}) %layer4_0_bn2 : [num_users=1] = call_module[target=layer4.0.bn2](args = (%layer4_0_conv2,), kwargs = {}) %layer4_0_downsample_0 : [num_users=1] = call_module[target=layer4.0.downsample.0](args = (%layer3_1_relu_1,), kwargs = {}) %layer4_0_downsample_1 : [num_users=1] = call_module[target=layer4.0.downsample.1](args = (%layer4_0_downsample_0,), kwargs = {}) %add_6 : [num_users=1] = call_function[target=operator.add](args = (%layer4_0_bn2, %layer4_0_downsample_1), kwargs = {}) %layer4_0_relu_1 : [num_users=2] = call_module[target=layer4.0.relu](args = (%add_6,), kwargs = {}) %layer4_1_conv1 : [num_users=1] = call_module[target=layer4.1.conv1](args = (%layer4_0_relu_1,), kwargs = {}) %layer4_1_bn1 : [num_users=1] = call_module[target=layer4.1.bn1](args = (%layer4_1_conv1,), kwargs = {}) %layer4_1_relu : [num_users=1] = call_module[target=layer4.1.relu](args = (%layer4_1_bn1,), kwargs = {}) %layer4_1_conv2 : [num_users=1] = call_module[target=layer4.1.conv2](args = (%layer4_1_relu,), kwargs = {}) %layer4_1_bn2 : [num_users=1] = call_module[target=layer4.1.bn2](args = (%layer4_1_conv2,), kwargs = {}) %add_7 : [num_users=1] = call_function[target=operator.add](args = (%layer4_1_bn2, %layer4_0_relu_1), kwargs = {}) %layer4_1_relu_1 : [num_users=1] = call_module[target=layer4.1.relu](args = (%add_7,), kwargs = {}) %avgpool : [num_users=1] = call_module[target=avgpool](args = (%layer4_1_relu_1,), kwargs = {}) %flatten : [num_users=1] = call_function[target=torch.flatten](args = (%avgpool, 1), kwargs = {}) %fc : [num_users=1] = call_module[target=fc](args = (%flatten,), kwargs = {}) return fc This gives us a Graph representation of the ResNet18 model. A Graph consists of a series of Nodes connected to each other. Each Node represents a call-site in the Python code (whether to a function, a module, or a method) and the edges (represented as args and kwargs on each node) represent the values passed between these call-sites. More information about the Graph representation and the rest of FX\u2019s APIs ca be found at the FX documentation https://pytorch.org/docs/master/fx.html. Creating a Profiling Interpreter# Next, we are going to create a class that inherits from torch.fx.Interpreter. Though the GraphModule that symbolic_trace produces compiles Python code that is run when you call a GraphModule, an alternative way to run a GraphModule is by executing each Node in the Graph one by one. That is the functionality that Interpreter provides: It interprets the graph node- by-node. By inheriting from Interpreter, we can override various functionality and install the profiling behavior we want. The goal is to have an object to which we can pass a model, invoke the model 1 or more times, then get statistics about how long the model and each part of the model took during those runs. Let\u2019s define our ProfilingInterpreter class: class ProfilingInterpreter(Interpreter): def __init__(self, mod : torch.nn.Module): # Rather than have the user symbolically trace their model, # we\u0027re going to do it in the constructor. As a result, the # user can pass in any ``Module`` without having to worry about # symbolic tracing APIs gm = torch.fx.symbolic_trace(mod) super().__init__(gm) # We are going to store away two things here: # # 1. A list of total runtimes for ``mod``. In other words, we are # storing away the time ``mod(...)`` took each time this # interpreter is called. self.total_runtime_sec : List[float] = [] # 2. A map from ``Node`` to a list of times (in seconds) that # node took to run. This can be seen as similar to (1) but # for specific sub-parts of the model. self.runtimes_sec : Dict[torch.fx.Node, List[float]] = {} ###################################################################### # Next, let\u0027s override our first method: ``run()``. ``Interpreter``\u0027s ``run`` # method is the top-level entry point for execution of the model. We will # want to intercept this so that we can record the total runtime of the # model. def run(self, *args) -\u003e Any: # Record the time we started running the model t_start = time.time() # Run the model by delegating back into Interpreter.run() return_val = super().run(*args) # Record the time we finished running the model t_end = time.time() # Store the total elapsed time this model execution took in the # ``ProfilingInterpreter`` self.total_runtime_sec.append(t_end - t_start) return return_val ###################################################################### # Now, let\u0027s override ``run_node``. ``Interpreter`` calls ``run_node`` each # time it executes a single node. We will intercept this so that we # can measure and record the time taken for each individual call in # the model. def run_node(self, n : torch.fx.Node) -\u003e Any: # Record the time we started running the op t_start = time.time() # Run the op by delegating back into Interpreter.run_node() return_val = super().run_node(n) # Record the time we finished running the op t_end = time.time() # If we don\u0027t have an entry for this node in our runtimes_sec # data structure, add one with an empty list value. self.runtimes_sec.setdefault(n, []) # Record the total elapsed time for this single invocation # in the runtimes_sec data structure self.runtimes_sec[n].append(t_end - t_start) return return_val ###################################################################### # Finally, we are going to define a method (one which doesn\u0027t override # any ``Interpreter`` method) that provides us a nice, organized view of # the data we have collected. def summary(self, should_sort : bool = False) -\u003e str: # Build up a list of summary information for each node node_summaries : List[List[Any]] = [] # Calculate the mean runtime for the whole network. Because the # network may have been called multiple times during profiling, # we need to summarize the runtimes. We choose to use the # arithmetic mean for this. mean_total_runtime = statistics.mean(self.total_runtime_sec) # For each node, record summary statistics for node, runtimes in self.runtimes_sec.items(): # Similarly, compute the mean runtime for ``node`` mean_runtime = statistics.mean(runtimes) # For easier understanding, we also compute the percentage # time each node took with respect to the whole network. pct_total = mean_runtime / mean_total_runtime * 100 # Record the node\u0027s type, name of the node, mean runtime, and # percent runtime. node_summaries.append( [node.op, str(node), mean_runtime, pct_total]) # One of the most important questions to answer when doing performance # profiling is \"Which op(s) took the longest?\". We can make this easy # to see by providing sorting functionality in our summary view if should_sort: node_summaries.sort(key=lambda s: s[2], reverse=True) # Use the ``tabulate`` library to create a well-formatted table # presenting our summary information headers : List[str] = [ \u0027Op type\u0027, \u0027Op\u0027, \u0027Average runtime (s)\u0027, \u0027Pct total runtime\u0027 ] return tabulate.tabulate(node_summaries, headers=headers) \ucc38\uace0 We use Python\u2019s time.time function to pull wall clock timestamps and compare them. This is not the most accurate way to measure performance, and will only give us a first- order approximation. We use this simple technique only for the purpose of demonstration in this tutorial. Investigating the Performance of ResNet18# We can now use ProfilingInterpreter to inspect the performance characteristics of our ResNet18 model; interp = ProfilingInterpreter(rn18) interp.run(input) print(interp.summary(True)) Op type Op Average runtime (s) Pct total runtime ------------- --------------------- --------------------- ------------------- call_module layer1_0_conv2 0.00284696 10.4592 call_module layer1_0_conv1 0.00282502 10.3787 call_module layer1_1_conv2 0.00265503 9.75413 call_module layer1_1_conv1 0.001688 6.20144 call_module conv1 0.00162578 5.97283 call_module layer2_1_conv2 0.00150108 5.51473 call_module layer2_0_downsample_0 0.000996351 3.66043 call_module bn1 0.000786543 2.88963 call_module layer4_0_conv2 0.000708818 2.60408 call_module layer4_1_conv2 0.000691652 2.54101 call_module layer2_1_conv1 0.000686884 2.5235 call_module layer4_0_conv1 0.000617743 2.26948 call_module layer3_1_conv1 0.000557661 2.04875 call_module layer4_1_conv1 0.0005126 1.88321 call_module layer3_1_conv2 0.000489712 1.79912 call_module layer3_0_downsample_0 0.00046134 1.69489 call_module layer3_0_conv2 0.000443697 1.63007 call_module maxpool 0.000440121 1.61693 call_function add 0.000430822 1.58277 call_module layer2_0_conv2 0.000421762 1.54948 call_module layer3_0_conv1 0.000375509 1.37956 call_function add_1 0.00037384 1.37343 call_module layer4_0_downsample_0 0.000359297 1.32 call_module layer2_0_conv1 0.000353336 1.2981 call_function add_2 0.000306845 1.1273 call_function add_3 0.000246048 0.903939 call_module avgpool 0.000120878 0.444086 call_module layer2_1_bn2 0.000117302 0.430948 call_module relu 0.000111103 0.408174 call_module layer1_0_bn1 0.000104666 0.384524 call_module layer1_1_bn2 8.72612e-05 0.320583 call_module layer1_0_bn2 8.70228e-05 0.319707 call_module fc 8.63075e-05 0.317079 call_module layer1_0_relu 8.44002e-05 0.310072 call_module layer4_1_bn2 8.13007e-05 0.298685 call_function add_5 7.93934e-05 0.291678 call_module layer1_1_bn1 7.89165e-05 0.289926 call_function add_7 7.89165e-05 0.289926 call_function add_6 7.77245e-05 0.285547 call_module layer3_1_bn2 7.36713e-05 0.270656 call_module layer2_0_bn1 7.22408e-05 0.265401 call_module layer2_1_relu 7.10487e-05 0.261021 call_module layer2_0_relu 7.03335e-05 0.258393 call_module layer2_1_bn1 7.00951e-05 0.257517 call_module layer4_0_bn2 6.98566e-05 0.256642 call_module layer3_0_bn2 6.91414e-05 0.254014 call_module layer2_0_bn2 6.86646e-05 0.252262 call_module layer3_0_bn1 6.77109e-05 0.248758 call_module layer1_1_relu 6.65188e-05 0.244379 call_module layer2_0_downsample_1 6.62804e-05 0.243503 call_module layer4_0_relu 6.60419e-05 0.242627 call_module layer4_1_bn1 6.50883e-05 0.239123 call_module layer3_0_relu 6.48499e-05 0.238247 call_function add_4 6.48499e-05 0.238247 call_module layer4_0_bn1 6.46114e-05 0.237372 call_module layer3_0_downsample_1 6.24657e-05 0.229488 call_module layer4_0_downsample_1 6.22272e-05 0.228612 call_module layer3_1_bn1 6.03199e-05 0.221605 call_module layer4_1_relu 5.96046e-05 0.218977 call_module layer3_1_relu 5.79357e-05 0.212846 call_module layer1_1_relu_1 5.62668e-05 0.206715 call_module layer4_0_relu_1 5.48363e-05 0.201459 call_module layer1_0_relu_1 5.38826e-05 0.197956 call_module layer3_0_relu_1 5.126e-05 0.188321 call_module layer4_1_relu_1 5.00679e-05 0.183941 call_module layer2_1_relu_1 4.91142e-05 0.180437 call_module layer3_1_relu_1 4.57764e-05 0.168175 call_module layer2_0_relu_1 4.50611e-05 0.165547 output output 2.81334e-05 0.103357 placeholder x 2.76566e-05 0.101606 call_function flatten 1.4782e-05 0.0543064 There are two things we should call out here: MaxPool2d takes up the most time. This is a known issue: pytorch/pytorch#51393 Conclusion# As we can see, using FX we can easily capture PyTorch programs (even ones we don\u2019t have the source code for!) in a machine-interpretable format and use that for analysis, such as the performance analysis we\u2019ve done here. FX opens up an exciting world of possibilities for working with PyTorch programs. Finally, since FX is still in beta, we would be happy to hear any feedback you have about using it. Please feel free to use the PyTorch Forums (https://discuss.pytorch.org/) and the issue tracker (pytorch/pytorch#issues) to provide any feedback you might have. Total running time of the script: (0 minutes 0.219 seconds) Download Jupyter notebook: fx_profiling_tutorial.ipynb Download Python source code: fx_profiling_tutorial.py Download zipped: fx_profiling_tutorial.zip",
       "author": {
         "@type": "Organization",
         "name": "PyTorch Contributors",
         "url": "https://pytorch.org"
       },
       "image": "../_static/img/pytorch_seo.png",
       "mainEntityOfPage": {
         "@type": "WebPage",
         "@id": "/intermediate/fx_profiling_tutorial.html"
       },
       "datePublished": "2023-01-01T00:00:00Z",
       "dateModified": "2023-01-01T00:00:00Z"
     }
 

article:modified_time2022-11-30T07:09:41+00:00
og:typearticle
og:site_namePyTorch Tutorials KR
og:image../_static/img/pytorch_seo.png
og:image:altPyTorch Tutorials KR
og:ignore_canonicaltrue
docsearch:languageko
docbuild:last-update2022년 11월 30일
None2
pytorch_projecttutorials

Links:

https://pytorch.kr/
PyTorch 시작하기 https://pytorch.kr/get-started/locally/
기본 익히기 https://tutorials.pytorch.kr/beginner/basics/intro.html
한국어 튜토리얼 https://tutorials.pytorch.kr/
한국어 모델 허브 https://pytorch.kr/hub/
Official Tutorials https://docs.pytorch.org/tutorials/
블로그 https://pytorch.kr/blog/
PyTorch API https://docs.pytorch.org/docs/
Domain API 소개 https://pytorch.kr/domains/
한국어 튜토리얼 https://tutorials.pytorch.kr/
Official Tutorials https://docs.pytorch.org/tutorials/
한국어 커뮤니티 https://discuss.pytorch.kr/
개발자 정보 https://pytorch.kr/resources/
Landscape https://landscape.pytorch.org/
https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html
https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html
PyTorch 시작하기https://pytorch.kr/get-started/locally/
기본 익히기https://tutorials.pytorch.kr/beginner/basics/intro.html
한국어 튜토리얼https://tutorials.pytorch.kr/
한국어 모델 허브https://pytorch.kr/hub/
Official Tutorialshttps://docs.pytorch.org/tutorials/
블로그https://pytorch.kr/blog/
PyTorch APIhttps://docs.pytorch.org/docs/
Domain API 소개https://pytorch.kr/domains/
한국어 튜토리얼https://tutorials.pytorch.kr/
Official Tutorialshttps://docs.pytorch.org/tutorials/
한국어 커뮤니티https://discuss.pytorch.kr/
개발자 정보https://pytorch.kr/resources/
Landscapehttps://landscape.pytorch.org/
Skip to main contenthttps://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#main-content
v2.8.0+cu128https://tutorials.pytorch.kr/index.html
Intro https://tutorials.pytorch.kr/intro.html
Compilers https://tutorials.pytorch.kr/compilers_index.html
Domains https://tutorials.pytorch.kr/domains.html
Distributed https://tutorials.pytorch.kr/distributed.html
Deep Dive https://tutorials.pytorch.kr/deep-dive.html
Extension https://tutorials.pytorch.kr/extension.html
Ecosystem https://tutorials.pytorch.kr/ecosystem.html
Recipes https://tutorials.pytorch.kr/recipes_index.html
한국어 튜토리얼 GitHub 저장소https://github.com/PyTorchKorea/tutorials-kr
파이토치 한국어 커뮤니티https://discuss.pytorch.kr/
Intro https://tutorials.pytorch.kr/intro.html
Compilers https://tutorials.pytorch.kr/compilers_index.html
Domains https://tutorials.pytorch.kr/domains.html
Distributed https://tutorials.pytorch.kr/distributed.html
Deep Dive https://tutorials.pytorch.kr/deep-dive.html
Extension https://tutorials.pytorch.kr/extension.html
Ecosystem https://tutorials.pytorch.kr/ecosystem.html
Recipes https://tutorials.pytorch.kr/recipes_index.html
한국어 튜토리얼 GitHub 저장소https://github.com/PyTorchKorea/tutorials-kr
파이토치 한국어 커뮤니티https://discuss.pytorch.kr/
Introduction to torch.compilehttps://tutorials.pytorch.kr/intermediate/torch_compile_tutorial.html
Compiled Autograd: Capturing a larger backward graph for torch.compilehttps://tutorials.pytorch.kr/intermediate/compiled_autograd_tutorial.html
Inductor CPU backend debugging and profilinghttps://tutorials.pytorch.kr/intermediate/inductor_debug_cpu.html
Dynamic Compilation Control with torch.compiler.set_stancehttps://tutorials.pytorch.kr/recipes/torch_compiler_set_stance_tutorial.html
Demonstration of torch.export flow, common challenges and the solutions to address themhttps://tutorials.pytorch.kr/recipes/torch_export_challenges_solutions.html
(beta) Compiling the optimizer with torch.compilehttps://tutorials.pytorch.kr/recipes/compiling_optimizer.html
(beta) Running the compiled optimizer with an LR Schedulerhttps://tutorials.pytorch.kr/recipes/compiling_optimizer_lr_scheduler.html
사용자 정의 Triton 커널을 ``torch.compile``과 함께 사용하기https://tutorials.pytorch.kr/recipes/torch_compile_user_defined_triton_kernel_tutorial.html
Compile Time Caching in torch.compilehttps://tutorials.pytorch.kr/recipes/torch_compile_caching_tutorial.html
Reducing torch.compile cold start compilation time with regional compilationhttps://tutorials.pytorch.kr/recipes/regional_compilation.html
torch.export Tutorialhttps://tutorials.pytorch.kr/intermediate/torch_export_tutorial.html
torch.export AOTInductor Tutorial for Python runtime (Beta)https://tutorials.pytorch.kr/recipes/torch_export_aoti_python.html
Demonstration of torch.export flow, common challenges and the solutions to address themhttps://tutorials.pytorch.kr/recipes/torch_export_challenges_solutions.html
Introduction to ONNXhttps://tutorials.pytorch.kr/beginner/onnx/intro_onnx.html
Export a PyTorch model to ONNXhttps://tutorials.pytorch.kr/beginner/onnx/export_simple_model_to_onnx_tutorial.html
Extending the ONNX Registryhttps://tutorials.pytorch.kr/beginner/onnx/onnx_registry_tutorial.html
Export a model with control flow to ONNXhttps://tutorials.pytorch.kr/beginner/onnx/export_control_flow_model_to_onnx_tutorial.html
Building a Convolution/Batch Norm fuser with torch.compilehttps://tutorials.pytorch.kr/intermediate/torch_compile_conv_bn_fuser.html
(beta) Building a Simple CPU Performance Profiler with FXhttps://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html
https://tutorials.pytorch.kr/index.html
Compilershttps://tutorials.pytorch.kr/compilers_index.html
Go to the endhttps://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#sphx-glr-download-intermediate-fx-profiling-tutorial-py
#https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#beta-building-a-simple-cpu-performance-profiler-with-fx
James Reedhttps://github.com/jamesr66a
#https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#capturing-the-model-with-symbolic-tracing
https://pytorch.org/docs/master/fx.htmlhttps://pytorch.org/docs/master/fx.html
#https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#creating-a-profiling-interpreter
#https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#investigating-the-performance-of-resnet18
pytorch/pytorch#51393https://github.com/pytorch/pytorch/issues/51393
#https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#conclusion
https://discuss.pytorch.org/https://discuss.pytorch.org/
pytorch/pytorch#issueshttps://github.com/pytorch/pytorch/issues
Download Jupyter notebook: fx_profiling_tutorial.ipynbhttps://tutorials.pytorch.kr/_downloads/945dab6b984b8789385e32187d4a8964/fx_profiling_tutorial.ipynb
Download Python source code: fx_profiling_tutorial.pyhttps://tutorials.pytorch.kr/_downloads/8c575aa36ad9a61584ec0ddf11cbe84d/fx_profiling_tutorial.py
Download zipped: fx_profiling_tutorial.ziphttps://tutorials.pytorch.kr/_downloads/b6301a206807fcf9ca7e4168fdc08e4a/fx_profiling_tutorial.zip
이전 Building a Convolution/Batch Norm fuser with torch.compile https://tutorials.pytorch.kr/intermediate/torch_compile_conv_bn_fuser.html
다음 Domains https://tutorials.pytorch.kr/domains.html
PyData Sphinx Themehttps://pydata-sphinx-theme.readthedocs.io/en/stable/index.html
이전 Building a Convolution/Batch Norm fuser with torch.compile https://tutorials.pytorch.kr/intermediate/torch_compile_conv_bn_fuser.html
다음 Domains https://tutorials.pytorch.kr/domains.html
Capturing the Model with Symbolic Tracinghttps://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#capturing-the-model-with-symbolic-tracing
Creating a Profiling Interpreterhttps://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#creating-a-profiling-interpreter
Investigating the Performance of ResNet18https://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#investigating-the-performance-of-resnet18
Conclusionhttps://tutorials.pytorch.kr/intermediate/fx_profiling_tutorial.html#conclusion
torchaohttps://docs.pytorch.org/ao
torchrechttps://docs.pytorch.org/torchrec
torchfthttps://docs.pytorch.org/torchft
TorchCodechttps://docs.pytorch.org/torchcodec
torchvisionhttps://docs.pytorch.org/vision
ExecuTorchhttps://docs.pytorch.org/executorch
PyTorch on XLA Deviceshttps://docs.pytorch.org/xla
GitHub로 이동https://github.com/PyTorchKorea
튜토리얼로 이동https://tutorials.pytorch.kr/
커뮤니티로 이동https://discuss.pytorch.kr/
https://pytorch.kr/
파이토치 한국 사용자 모임https://pytorch.kr/
사용자 모임 소개https://pytorch.kr/about
기여해주신 분들https://pytorch.kr/contributors
리소스https://pytorch.kr/resources/
행동 강령https://pytorch.kr/coc
행동 강령https://pytorch.kr/coc
Linux Foundation의 정책https://www.linuxfoundation.org/policies/
our code of conducthttps://pytorch.kr/coc
Linux Foundation's policieshttps://www.linuxfoundation.org/policies/
Cookies Policyhttps://www.facebook.com/policies/cookies/
Sphinxhttps://www.sphinx-doc.org/
PyData Sphinx Themehttps://pydata-sphinx-theme.readthedocs.io/en/stable/index.html

Viewport: width=device-width, initial-scale=1


URLs of crawlers that visited me.