{
  "version": "1.1",
  "slug": "how-pytorch-runs",
  "title": "What Actually Happens When You Run a PyTorch Model? | Language Lineage",
  "h1": "What Actually Happens When You Run a PyTorch Model?",
  "description": "Trace a PyTorch model from Python to the hardware: eager mode vs torch.compile, CPU vs GPU, through ATen, TorchDynamo, TorchInductor, Triton, LLVM IR and PTX, with sources.",
  "og_subtitle": "Python → TorchDynamo → TorchInductor → Triton → LLVM IR → PTX → GPU",
  "verified_on": "2026-11-10",
  "verified_against": "PyTorch 2.15 documentation, Triton main README, NVIDIA PTX ISA documentation",
  "scope": "Illustrative, documented paths for one PyTorch program in eager mode and under torch.compile with the default TorchInductor backend, on a CPU or an NVIDIA GPU. Not every PyTorch program takes these paths: other torch.compile backends, AMD and Intel GPUs, Apple MPS, CUDA graphs and custom operators are out of scope.",
  "answer": "In **eager mode**, each tensor operation in your Python code is a separate call into ATen, PyTorch's C++ core, which runs a precompiled C++ kernel on the CPU or a CUDA kernel on the GPU. With **torch.compile**, TorchDynamo captures runs of operations as an FX graph, and TorchInductor generates new kernels for it: C++ with OpenMP for CPUs, Triton for GPUs. On an NVIDIA GPU, Triton lowers each kernel through MLIR and LLVM IR to PTX, which NVIDIA's driver turns into the GPU's own machine code.",
  "status_template": "Showing {mode} on {device}",
  "dimensions": [
    {
      "id": "mode",
      "legend": "Mode",
      "default": "compile",
      "options": [
        {
          "value": "eager",
          "label": "Eager",
          "phrase": "eager mode"
        },
        {
          "value": "compile",
          "label": "torch.compile",
          "phrase": "torch.compile"
        }
      ]
    },
    {
      "id": "device",
      "legend": "Device",
      "default": "gpu",
      "options": [
        {
          "value": "cpu",
          "label": "CPU",
          "phrase": "a CPU"
        },
        {
          "value": "gpu",
          "label": "NVIDIA GPU",
          "phrase": "an NVIDIA GPU"
        }
      ]
    }
  ],
  "sections": [
    {
      "heading": "Where Python ends",
      "paragraphs": [
        "In eager mode, Python's part ends at each operation's call into ATen: from there on, everything is precompiled C++ and CUDA that shipped inside PyTorch. Python is still in charge of the order of operations, one call at a time, so the interpreter's overhead is paid on every operation.",
        "Under torch.compile, Python's part ends earlier for the code TorchDynamo can capture: the captured operations never run as individual Python calls again. They become an FX graph, then new code generated by TorchInductor, and on a GPU that code passes through three compiler stages (Triton, LLVM, PTX) before NVIDIA's driver produces machine code for the specific GPU. Code Dynamo cannot trace causes a graph break and still runs in normal Python between compiled graphs.",
        "Either way the GPU work is asynchronous: Python queues kernels and moves on, which is why a GPU program can look fast until something forces it to wait for a result."
      ]
    }
  ],
  "out_of_scope_note": "TorchInductor's GPU path through Triton also serves AMD and Intel GPUs, ending in a different final format (for AMD, AMDGCN instead of PTX). Other torch.compile backends replace TorchInductor entirely.",
  "link_from": [
    "tool:pytorch",
    "tool:cuda",
    "tool:llvm",
    "lang:python",
    "tool:triton"
  ],
  "sources": {
    "dynamo": {
      "url": "https://docs.pytorch.org/docs/main/user_guide/torch_compiler/torch.compiler_dynamo_overview.html",
      "title": "Dynamo Overview (PyTorch documentation)"
    },
    "graph_breaks": {
      "url": "https://docs.pytorch.org/docs/2.15/user_guide/torch_compiler/compile/programming_model.graph_breaks_index.html",
      "title": "Working with Graph Breaks (PyTorch 2.15 documentation)"
    },
    "torch_compiler": {
      "url": "https://docs.pytorch.org/docs/2.15/user_guide/torch_compiler/torch.compiler.html",
      "title": "torch.compiler (PyTorch 2.15 documentation)"
    },
    "pt2_paper": {
      "url": "https://pytorch.org/blog/pytorch-pytorch-2-paper-tutorial/",
      "title": "PyTorch 2 paper and tutorial (PyTorch blog)"
    },
    "inductor_design": {
      "url": "https://dev-discuss.pytorch.org/t/torchinductor-a-pytorch-native-compiler-with-define-by-run-ir-and-symbolic-shapes/747",
      "title": "TorchInductor design post by its lead author (PyTorch dev-discuss)"
    },
    "aten": {
      "url": "https://docs.pytorch.org/cppdocs/",
      "title": "PyTorch C++ API: ATen (PyTorch documentation)"
    },
    "cuda_notes": {
      "url": "https://docs.pytorch.org/docs/2.15/notes/cuda.html",
      "title": "CUDA semantics (PyTorch 2.15 documentation)"
    },
    "triton_docs": {
      "url": "https://triton-lang.org/main/index.html",
      "title": "Triton documentation"
    },
    "triton_readme": {
      "url": "https://github.com/triton-lang/triton/blob/main/README.md",
      "title": "Triton README (triton-lang/triton)"
    },
    "ptx": {
      "url": "https://docs.nvidia.com/cuda/parallel-thread-execution/index.html",
      "title": "PTX ISA (NVIDIA documentation)"
    }
  },
  "stages": [
    {
      "id": "python_code",
      "name": "Your model code",
      "kind": "programming_language",
      "layer": "python",
      "lineage_id": "lang:python",
      "summary": "The nn.Module and training or inference loop you write in Python. Every tensor operation in it is a call into PyTorch.",
      "evidence": [
        {
          "source": "aten",
          "quote": "ATen is fundamentally a tensor library, on top of which almost all other Python and C++ interfaces in PyTorch are built."
        }
      ],
      "pos": [
        1.5,
        0
      ]
    },
    {
      "id": "cpython",
      "name": "CPython interpreter",
      "kind": "runtime",
      "layer": "python",
      "lineage_id": "lang:python",
      "summary": "Runs your Python bytecode. In eager mode it calls PyTorch one operation at a time; under torch.compile, TorchDynamo hooks into it before each frame runs.",
      "evidence": [
        {
          "source": "dynamo",
          "quote": "Dynamo hooks into the frame evaluation API in CPython (PEP 523) to dynamically modify Python bytecode right before it is executed."
        }
      ],
      "pos": [
        1.5,
        1
      ]
    },
    {
      "id": "aten",
      "name": "ATen dispatch",
      "kind": "framework_component",
      "layer": "framework",
      "lineage_id": "tool:pytorch",
      "summary": "PyTorch's C++ tensor library. Each operation is looked up and sent to the implementation for the tensor's device and type.",
      "evidence": [
        {
          "source": "aten",
          "quote": "Most of these operations have both CPU and GPU implementations, to which the Tensor class will dynamically dispatch based on its type."
        }
      ],
      "pos": [
        0.5,
        2
      ]
    },
    {
      "id": "aten_cpu",
      "name": "ATen CPU kernels",
      "kind": "kernel",
      "layer": "framework",
      "lineage_id": "lang:cxx",
      "summary": "Precompiled C++ implementations of each operation for the CPU, shipped inside the PyTorch library.",
      "evidence": [
        {
          "source": "aten",
          "quote": "Most of these operations have both CPU and GPU implementations, to which the Tensor class will dynamically dispatch based on its type."
        }
      ],
      "pos": [
        0,
        3
      ]
    },
    {
      "id": "aten_cuda",
      "name": "ATen CUDA kernels",
      "kind": "kernel",
      "layer": "framework",
      "lineage_id": "tool:cuda",
      "summary": "Precompiled GPU implementations of each operation. Some, such as matrix multiplications, call NVIDIA's cuBLAS library.",
      "evidence": [
        {
          "source": "aten",
          "quote": "Most of these operations have both CPU and GPU implementations, to which the Tensor class will dynamically dispatch based on its type."
        },
        {
          "source": "cuda_notes",
          "quote": "Under torch.compile, FP32 matmuls using bfx9 remain ATen/cuBLAS calls"
        }
      ],
      "pos": [
        1,
        3
      ]
    },
    {
      "id": "dynamo",
      "name": "TorchDynamo",
      "kind": "compiler",
      "layer": "compiler",
      "lineage_id": null,
      "summary": "A Python-level JIT compiler. It rewrites your function's bytecode so that runs of PyTorch operations are captured as a graph instead of executed one by one.",
      "evidence": [
        {
          "source": "dynamo",
          "quote": "It rewrites Python bytecode to extract sequences of PyTorch operations into an FX Graph which is then compiled with a customizable backend."
        }
      ],
      "pos": [
        2.5,
        2
      ]
    },
    {
      "id": "fx_graph",
      "name": "FX graph",
      "kind": "intermediate_representation",
      "layer": "compiler",
      "lineage_id": null,
      "summary": "The captured sequence of PyTorch operations, as a graph a backend compiler can optimize. Code Dynamo cannot trace causes a graph break and runs in normal Python between graphs.",
      "evidence": [
        {
          "source": "dynamo",
          "quote": "It rewrites Python bytecode to extract sequences of PyTorch operations into an FX Graph which is then compiled with a customizable backend."
        },
        {
          "source": "graph_breaks",
          "quote": "Dynamo performs a graph break when it encounters code that can't be traced."
        }
      ],
      "pos": [
        2.5,
        3
      ]
    },
    {
      "id": "inductor",
      "name": "TorchInductor",
      "kind": "compiler",
      "layer": "compiler",
      "lineage_id": null,
      "summary": "The default torch.compile backend. It generates new kernels for the graph: Triton for GPUs and C++ for CPUs. For training, AOT Autograd also captures the backward pass ahead of time.",
      "evidence": [
        {
          "source": "torch_compiler",
          "quote": "The default backend is called TorchInductor"
        },
        {
          "source": "pt2_paper",
          "quote": "TorchInductor is the default compiler backend for TorchDynamo, which translates PyTorch programs into OpenAI's Triton for GPUs and C++ for CPUs."
        },
        {
          "source": "torch_compiler",
          "quote": "AOT Autograd captures not only the user-level code, but also backpropagation"
        },
        {
          "source": "inductor_design",
          "quote": "Pointwise ops can be fused with: other pointwise ops; reduction ops; and matmul/conv templates."
        }
      ],
      "pos": [
        2.5,
        4
      ]
    },
    {
      "id": "cpp_openmp",
      "name": "C++/OpenMP kernels",
      "kind": "kernel",
      "layer": "kernel",
      "lineage_id": "lang:cxx",
      "summary": "On CPU, Inductor writes C++ kernels that use OpenMP to spread work across cores, usually fusing several operations into one kernel.",
      "evidence": [
        {
          "source": "pt2_paper",
          "quote": "TorchInductor is the default compiler backend for TorchDynamo, which translates PyTorch programs into OpenAI's Triton for GPUs and C++ for CPUs."
        },
        {
          "source": "inductor_design",
          "quote": "OpenMP provides a work sharing parallel execution model, and enables support for CPUs."
        }
      ],
      "pos": [
        2,
        5
      ]
    },
    {
      "id": "triton_kernels",
      "name": "Triton kernels",
      "kind": "kernel_language",
      "layer": "kernel",
      "lineage_id": "tool:triton",
      "summary": "On GPU, Inductor writes kernels in Triton, a Python-embedded language for GPU programming, usually fusing several operations into one kernel.",
      "evidence": [
        {
          "source": "torch_compiler",
          "quote": "For NVIDIA, AMD and Intel GPUs, it leverages OpenAI Triton as the key building block."
        },
        {
          "source": "triton_docs",
          "quote": "Triton is a language and compiler for parallel programming."
        }
      ],
      "pos": [
        3,
        5
      ]
    },
    {
      "id": "triton_compiler",
      "name": "Triton compiler",
      "kind": "compiler",
      "layer": "compiler",
      "lineage_id": "tool:triton",
      "summary": "Compiles each Triton kernel through a series of MLIR passes, then hands it to LLVM for code generation.",
      "evidence": [
        {
          "source": "triton_docs",
          "quote": "Triton is a language and compiler for parallel programming."
        },
        {
          "source": "triton_readme",
          "quote": "MLIR_ENABLE_DUMP=1 dumps the IR before every MLIR pass Triton runs, for all kernels."
        }
      ],
      "pos": [
        3,
        6
      ]
    },
    {
      "id": "llvm_ir",
      "name": "LLVM IR",
      "kind": "intermediate_representation",
      "layer": "compiler",
      "lineage_id": "tool:llvm",
      "summary": "LLVM's intermediate representation. Triton uses LLVM to generate the device code.",
      "evidence": [
        {
          "source": "triton_readme",
          "quote": "Triton uses LLVM to generate code for GPUs and CPUs."
        }
      ],
      "pos": [
        3,
        7
      ]
    },
    {
      "id": "ptx",
      "name": "PTX",
      "kind": "intermediate_representation",
      "layer": "compiler",
      "lineage_id": "tool:cuda",
      "summary": "NVIDIA's virtual instruction set, the last portable step. It is not yet the GPU's own machine code.",
      "evidence": [
        {
          "source": "triton_readme",
          "quote": "TRITON_KERNEL_DUMP enables the dumping of the IR from each compilation stage and the final ptx/amdgcn."
        },
        {
          "source": "ptx",
          "quote": "PTX defines a virtual machine and ISA for general purpose parallel thread execution."
        }
      ],
      "pos": [
        3,
        8
      ]
    },
    {
      "id": "gpu_machine_code",
      "name": "GPU machine code",
      "kind": "machine_code",
      "layer": "hardware",
      "lineage_id": "lang:machine_code",
      "summary": "The instructions of one specific GPU architecture, produced from PTX by NVIDIA's translator and driver.",
      "evidence": [
        {
          "source": "ptx",
          "quote": "The PTX-to-GPU translator and driver enable NVIDIA GPUs to be used as programmable parallel computers."
        }
      ],
      "pos": [
        3,
        9
      ]
    },
    {
      "id": "cpu",
      "name": "CPU",
      "kind": "hardware",
      "layer": "hardware",
      "lineage_id": null,
      "summary": "Runs the compiled C++ kernels directly, across its cores.",
      "evidence": [
        {
          "source": "inductor_design",
          "quote": "OpenMP provides a work sharing parallel execution model, and enables support for CPUs."
        }
      ],
      "pos": [
        0.75,
        10
      ]
    },
    {
      "id": "nvidia_gpu",
      "name": "NVIDIA GPU",
      "kind": "hardware",
      "layer": "hardware",
      "lineage_id": null,
      "summary": "Runs kernels launched from the CPU. Launches are queued, so Python usually returns before the GPU has finished.",
      "evidence": [
        {
          "source": "cuda_notes",
          "quote": "By default, GPU operations are asynchronous. When you call a function that uses the GPU, the operations are enqueued to the particular device, but not necessarily executed until later."
        }
      ],
      "pos": [
        2.5,
        10
      ]
    }
  ],
  "steps": [
    {
      "from": "python_code",
      "to": "cpython",
      "kind": "runs_in",
      "when": {},
      "label": "runs in",
      "explanation": "Your model is ordinary Python, executed by the CPython interpreter.",
      "evidence": [
        {
          "source": "dynamo",
          "quote": "Dynamo hooks into the frame evaluation API in CPython (PEP 523) to dynamically modify Python bytecode right before it is executed."
        }
      ]
    },
    {
      "from": "cpython",
      "to": "aten",
      "kind": "calls",
      "when": {
        "mode": [
          "eager"
        ]
      },
      "label": "calls, one op at a time",
      "explanation": "In eager mode each tensor operation is a separate call from Python into PyTorch's C++ core.",
      "evidence": [
        {
          "source": "aten",
          "quote": "ATen is fundamentally a tensor library, on top of which almost all other Python and C++ interfaces in PyTorch are built."
        }
      ]
    },
    {
      "from": "aten",
      "to": "aten_cpu",
      "kind": "dispatches_to",
      "when": {
        "mode": [
          "eager"
        ],
        "device": [
          "cpu"
        ]
      },
      "label": "dispatches to",
      "explanation": "For CPU tensors, ATen picks the CPU implementation of the operation.",
      "evidence": [
        {
          "source": "aten",
          "quote": "Most of these operations have both CPU and GPU implementations, to which the Tensor class will dynamically dispatch based on its type."
        }
      ]
    },
    {
      "from": "aten",
      "to": "aten_cuda",
      "kind": "dispatches_to",
      "when": {
        "mode": [
          "eager"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "dispatches to",
      "explanation": "For CUDA tensors, ATen picks the GPU implementation of the operation.",
      "evidence": [
        {
          "source": "aten",
          "quote": "Most of these operations have both CPU and GPU implementations, to which the Tensor class will dynamically dispatch based on its type."
        }
      ]
    },
    {
      "from": "aten_cpu",
      "to": "cpu",
      "kind": "executes_on",
      "when": {
        "device": [
          "cpu"
        ]
      },
      "label": "runs on",
      "explanation": "The precompiled C++ kernel runs on the CPU.",
      "evidence": [
        {
          "source": "aten",
          "quote": "Most of these operations have both CPU and GPU implementations, to which the Tensor class will dynamically dispatch based on its type."
        }
      ]
    },
    {
      "from": "aten_cuda",
      "to": "nvidia_gpu",
      "kind": "launches_on",
      "when": {
        "device": [
          "gpu"
        ]
      },
      "label": "launched on",
      "explanation": "The kernel is queued on the GPU; Python continues without waiting for it to finish.",
      "evidence": [
        {
          "source": "cuda_notes",
          "quote": "By default, GPU operations are asynchronous. When you call a function that uses the GPU, the operations are enqueued to the particular device, but not necessarily executed until later."
        }
      ]
    },
    {
      "from": "cpython",
      "to": "dynamo",
      "kind": "intercepted_by",
      "when": {
        "mode": [
          "compile"
        ]
      },
      "label": "intercepted by",
      "explanation": "With torch.compile, TorchDynamo hooks CPython's frame evaluation and rewrites the function's bytecode before it runs.",
      "evidence": [
        {
          "source": "dynamo",
          "quote": "Dynamo hooks into the frame evaluation API in CPython (PEP 523) to dynamically modify Python bytecode right before it is executed."
        }
      ]
    },
    {
      "from": "dynamo",
      "to": "fx_graph",
      "kind": "captures",
      "when": {
        "mode": [
          "compile"
        ]
      },
      "label": "captures",
      "explanation": "Sequences of PyTorch operations become an FX graph. Code that cannot be traced causes a graph break and runs in normal Python between graphs.",
      "evidence": [
        {
          "source": "dynamo",
          "quote": "It rewrites Python bytecode to extract sequences of PyTorch operations into an FX Graph which is then compiled with a customizable backend."
        },
        {
          "source": "graph_breaks",
          "quote": "Dynamo performs a graph break when it encounters code that can't be traced."
        }
      ]
    },
    {
      "from": "fx_graph",
      "to": "inductor",
      "kind": "compiled_by",
      "when": {
        "mode": [
          "compile"
        ]
      },
      "label": "compiled by",
      "explanation": "The graph goes to the backend compiler; by default that is TorchInductor.",
      "evidence": [
        {
          "source": "torch_compiler",
          "quote": "The default backend is called TorchInductor"
        }
      ]
    },
    {
      "from": "inductor",
      "to": "cpp_openmp",
      "kind": "generates",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "cpu"
        ]
      },
      "label": "generates",
      "explanation": "For CPU, Inductor generates C++ kernels parallelized with OpenMP.",
      "evidence": [
        {
          "source": "pt2_paper",
          "quote": "TorchInductor is the default compiler backend for TorchDynamo, which translates PyTorch programs into OpenAI's Triton for GPUs and C++ for CPUs."
        },
        {
          "source": "inductor_design",
          "quote": "OpenMP provides a work sharing parallel execution model, and enables support for CPUs."
        }
      ]
    },
    {
      "from": "inductor",
      "to": "triton_kernels",
      "kind": "generates",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "generates",
      "explanation": "For GPUs, Inductor generates Triton kernels.",
      "evidence": [
        {
          "source": "pt2_paper",
          "quote": "TorchInductor is the default compiler backend for TorchDynamo, which translates PyTorch programs into OpenAI's Triton for GPUs and C++ for CPUs."
        },
        {
          "source": "torch_compiler",
          "quote": "For NVIDIA, AMD and Intel GPUs, it leverages OpenAI Triton as the key building block."
        }
      ]
    },
    {
      "from": "inductor",
      "to": "aten_cpu",
      "kind": "falls_back_to",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "cpu"
        ]
      },
      "label": "some ops fall back to",
      "explanation": "Operations Inductor does not generate code for are still run by the existing ATen kernels.",
      "evidence": [
        {
          "source": "inductor_design",
          "quote": "There is also a small list of kernels we haven't implemented yet and are using aten fallbacks"
        }
      ]
    },
    {
      "from": "inductor",
      "to": "aten_cuda",
      "kind": "falls_back_to",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "some ops stay",
      "explanation": "Some operations stay ATen calls under torch.compile, for example certain matrix multiplications that remain cuBLAS calls.",
      "evidence": [
        {
          "source": "cuda_notes",
          "quote": "Under torch.compile, FP32 matmuls using bfx9 remain ATen/cuBLAS calls"
        },
        {
          "source": "inductor_design",
          "quote": "There is also a small list of kernels we haven't implemented yet and are using aten fallbacks"
        }
      ]
    },
    {
      "from": "cpp_openmp",
      "to": "cpu",
      "kind": "executes_on",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "cpu"
        ]
      },
      "label": "runs on",
      "explanation": "The compiled C++ kernels run on the CPU, split across cores by OpenMP.",
      "evidence": [
        {
          "source": "inductor_design",
          "quote": "OpenMP provides a work sharing parallel execution model, and enables support for CPUs."
        }
      ]
    },
    {
      "from": "triton_kernels",
      "to": "triton_compiler",
      "kind": "compiled_by",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "compiled by",
      "explanation": "Each Triton kernel is compiled by the Triton compiler, which runs a series of MLIR passes.",
      "evidence": [
        {
          "source": "triton_readme",
          "quote": "MLIR_ENABLE_DUMP=1 dumps the IR before every MLIR pass Triton runs, for all kernels."
        }
      ]
    },
    {
      "from": "triton_compiler",
      "to": "llvm_ir",
      "kind": "lowers_to",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "lowers to",
      "explanation": "Triton lowers the kernel to LLVM IR and uses LLVM for code generation.",
      "evidence": [
        {
          "source": "triton_readme",
          "quote": "Triton uses LLVM to generate code for GPUs and CPUs."
        }
      ]
    },
    {
      "from": "llvm_ir",
      "to": "ptx",
      "kind": "lowers_to",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "lowers to",
      "explanation": "For NVIDIA GPUs the final stage of Triton's pipeline is PTX (for AMD GPUs it is AMDGCN instead).",
      "evidence": [
        {
          "source": "triton_readme",
          "quote": "TRITON_KERNEL_DUMP enables the dumping of the IR from each compilation stage and the final ptx/amdgcn."
        }
      ]
    },
    {
      "from": "ptx",
      "to": "gpu_machine_code",
      "kind": "translated_to",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "translated to",
      "explanation": "NVIDIA's translator and driver turn portable PTX into the machine code of the installed GPU.",
      "evidence": [
        {
          "source": "ptx",
          "quote": "The PTX-to-GPU translator and driver enable NVIDIA GPUs to be used as programmable parallel computers."
        }
      ]
    },
    {
      "from": "gpu_machine_code",
      "to": "nvidia_gpu",
      "kind": "launches_on",
      "when": {
        "mode": [
          "compile"
        ],
        "device": [
          "gpu"
        ]
      },
      "label": "launched on",
      "explanation": "The compiled kernel is launched on the GPU, asynchronously, like any other CUDA kernel.",
      "evidence": [
        {
          "source": "cuda_notes",
          "quote": "By default, GPU operations are asynchronous. When you call a function that uses the GPU, the operations are enqueued to the particular device, but not necessarily executed until later."
        }
      ]
    }
  ]
}
