<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      MPK(Mirage Persistent Kernel)源碼筆記(3)--- 系統接口

      MPK(Mirage Persistent Kernel)源碼筆記(3)--- 系統接口

      0x00 概述

      因為轉譯系統需要通過persistent_kernel.py來完成,所以我們先介紹persistent_kernel.py。

      persistent_kernel.py是 Persistent Kernel的Python接口,本質是Python到CUDA持久化內核系統的橋梁,允許用戶用python定義復雜的計算圖,然后在GPU上高效執行。主要功能包括:

      • 持久化內核管理。提供了 PersistentKernel 作為接口類來管理和執行持久化CUDA內核。
      • 內核編譯。將Python定義的計算圖編譯為CUDA代碼并生成共享庫。集成了nvcc編譯器來編譯生成CUDA代碼。
      • 內核執行。提供接口來初始化、啟動和執行持久化內核。

      此外,在 HARD_CODE 定義的C函數是底層入口點,具體如下:

      • init_func:初始化內核。
      • launch_func:啟動內核執行。會調用到 launch_persistent_kernel。
      • finalize_func:清理和終止內核。

      0x01 流程

      persistent_kernel.py的工作流程如下:

      • 初始化:創建 PersistentKernel 類。
      • 定義計算圖:使用各種layer方法(如embed_layer、attention_layer等)定義計算圖。
      • 編譯。調用compile()方法生成和編譯CUDA內核。
        • 生成任務圖。
        • 創建CUDA代碼。
        • 調用nvcc編譯器。
        • 創建Python綁定模塊
      • 執行:調用call()方法啟動內核執行。 self.launch_func()
      • 清理:調用finalize()方法或者自動析構。

      具體如下圖所示。

      3-1

      0x02 初始化

      初始化函數會創建 PersistentKernel 類。

      因為此處只是系統接口,大部分有意義的工作在C++代碼中實現,因此此處略過。

      class PersistentKernel:
          def __init__(
              self,
              world_size: int,
              mpi_rank: int,
              num_workers: int,
              num_local_schedulers: int,
              num_remote_schedulers: int,
              max_seq_length: int,
              eos_token_id: int64,
              meta_tensors: list[torch.Tensor],
              profiler_tensor: torch.Tensor,
              spec_decode_config: SpecDecodeConfig
          ):
              self.__finalized__ = False
              self._is_compiled = False
              self.world_size = world_size
              self.mpi_rank = mpi_rank
              self.num_workers = num_workers
              self.num_local_schedulers = num_local_schedulers
              self.num_remote_schedulers = num_remote_schedulers
              self.max_seq_length = max_seq_length
              self.eos_token_id = eos_token_id
              self.kn_graph = KNGraph(CyKNGraph(disable_fingerprint=True))
              self.meta_tensors = meta_tensors
              self.profiler_tensor = profiler_tensor
              self.use_nvshmem = True if world_size > 1 else False
              self.spec_decode_config = spec_decode_config
              self._spec_decode_handlers = {
                  "promptlookup": self.prompt_lookup_spec_handler,
              }
              self._spec_verify_handlers = {
                  "promptlookup": self.prompt_lookup_verify_handler,
              }
      

      0x03 定義計算圖

      persistent_kernel.py 使用各種layer方法(如embed_layer、attention_layer等)定義計算圖。簡易流程如下:

      MPK-3-2

      對應的代碼舉例如下:

          def attach_input(self, torch_tensor: torch.Tensor, name: str = None) -> DTensor:
              """
              將PyTorch張量附加到計算圖,創建對應的DTensor(分布式張量)。
              
              參數:
                  torch_tensor: 待附加的PyTorch張量
                  name: 張量名稱(必須指定)
              返回:
                  與輸入張量關聯的DTensor實例
              說明:
                  僅支持行優先(row-major)內存布局,通過步長校驗確保布局正確性
              """
              # 提取張量維度與步長信息
              dims = tuple([d for d in torch_tensor.shape])
              strides = tuple([s for s in torch_tensor.stride()])
              
              # 校驗是否為行優先布局(高維步長 = 低維步長 × 低維尺寸)
              for d in range(len(dims) - 1):
                  assert strides[d] == strides[d + 1] * dims[d + 1]
              
              # 轉換PyTorch數據類型為框架內部 dtype
              dtype = convert_torch_type_to_dtype(torch_tensor.dtype)
              
              # 創建輸入張量節點
              t = self.kn_graph.new_input(dims=dims, strides=strides, dtype=dtype)
              
              # 斷言名稱非空(當前實現限制)
              assert name is not None
              
              # 將DTensor與PyTorch張量綁定,并注冊到計算圖
              self.kn_graph.attach_torch_tensor(t, torch_tensor, name)
              return t
      
          def new_tensor(
              self,
              dims: tuple,
              strides: tuple = None,
              dtype: dtype = bfloat16,
              name: str = None,
              io_category: str = "cuda_tensor",
          ) -> DTensor:
              """
              創建新的DTensor并根據IO類別附加到計算圖。
              
              參數:
                  dims: 張量維度元組
                  strides: 步長元組(默認自動按行優先計算)
                  dtype: 數據類型(默認bfloat16)
                  name: 張量名稱(必須指定)
                  io_category: IO類別("cuda_tensor"或"nvshmem_tensor")
              返回:
                  新創建的DTensor實例
              說明:
                  支持CUDA本地張量與NVSHMEM分布式張量兩種類型
              """
              # 若指定步長,校驗是否為行優先布局
              if strides is not None:
                  for d in range(len(dims) - 1):
                      assert strides[d] == strides[d + 1] * dims[d + 1]
              
              # 創建張量節點
              t = self.kn_graph.new_input(dims=dims, strides=strides, dtype=dtype)
              
              # 斷言名稱非空(當前實現限制)
              assert name is not None
              
              # 根據IO類別綁定張量到計算圖
              if io_category == "cuda_tensor":
                  self.kn_graph.attach_cuda_tensor(t, name)  # 綁定CUDA張量
              elif io_category == "nvshmem_tensor":
                  self.kn_graph.attach_nvshmem_tensor(t, name)  # 綁定NVSHMEM分布式張量
              else:
                  raise RuntimeError(f"Invalid io_category: {io_category}")
              return t
      
          def fuse_tensors(
              self, inputs: list[DTensor], fused_dim: int, num_groups: int, name: str = None
          ) -> DTensor:
              """
              融合多個張量到單個張量(當前僅支持第0維融合)。
              
              參數:
                  inputs: 待融合的DTensor列表
                  fused_dim: 融合維度(必須為0)
                  num_groups: 分組數量
                  name: 融合后張量名稱
              返回:
                  融合后的DTensor實例
              """
              # 當前僅支持第0維融合
              assert fused_dim == 0
              
              # 調用計算圖的張量融合接口
              t = self.kn_graph.fuse_tensors(inputs, fused_dim, num_groups, name)
              return t
      
          def embed_layer(
              self,
              input: DTensor,  # 輸入張量 [batch_size, num_spec_tokens]
              weight: DTensor,  # 嵌入權重 [vocab_size, hidden_size]
              output: DTensor,  # 輸出張量 [batch_size, hidden_size]
              grid_dim: tuple,  # CUDA網格維度
              block_dim: tuple,  # CUDA塊維度
              input_source: int = 0,  # 輸入源類型(0: 全 tokens, 1: 輸入 token)
          ):
              """
              定義嵌入層計算,將輸入張量通過嵌入權重映射到隱藏空間。
              
              參數:
                  input: 輸入張量
                  weight: 嵌入權重張量
                  output: 輸出張量(用于存儲結果)
                  grid_dim: CUDA kernel的網格維度
                  block_dim: CUDA kernel的塊維度
                  input_source: 輸入源類型標記
              說明:
                  內部創建線程塊圖(TBGraph),定義輸入輸出映射關系,并注冊為"embedding"任務
              """
              # 創建線程塊圖(CyTBGraph為底層實現,64為共享內存大?。?        tb_graph = TBGraph(CyTBGraph(grid_dim, block_dim, 1, 64))
              
              # 定義輸入輸出張量的維度映射規則
              tb_graph.new_input(input, (-1, 1, -1), -1, True)  # 輸入張量維度映射
              tb_graph.new_input(weight, (1, -1, -1), -1, True)  # 權重張量維度映射
              tb_graph.new_input(output, (1, 0, -1), -1, True)  # 輸出張量維度映射
              
              # 將張量與線程塊圖關聯
              self.kn_graph.customized([input, weight, output], tb_graph)
              
              # 注冊嵌入層任務,附加輸入源參數
              self.kn_graph.register_task(tb_graph, "embedding", [input_source])
      
          def rmsnorm_linear_layer(
              self,
              input: DTensor,  # 輸入張量
              weight_norm: DTensor,  # 歸一化權重
              weight_linear: DTensor,  # 線性層權重
              output: DTensor,  # 輸出張量
              grid_dim: tuple,  # CUDA網格維度
              block_dim: tuple,  # CUDA塊維度
          ):
              """
              定義RMS歸一化+線性變換組合層。
              
              參數:
                  input: 輸入張量(2D)
                  weight_norm: RMS歸一化權重(2D)
                  weight_linear: 線性層權重(2D)
                  output: 輸出張量(2D)
                  grid_dim: CUDA kernel的網格維度
                  block_dim: CUDA kernel的塊維度
              說明:
                  先對輸入執行RMS歸一化,再通過線性層變換,輸出結果存儲到output
              """
              # 校驗輸入張量維度(當前僅支持2D張量)
              assert input.num_dims == 2
              assert weight_linear.num_dims == 2
              assert output.num_dims == 2
              
              # 創建線程塊圖
              tb_graph = TBGraph(CyTBGraph(grid_dim, block_dim, 1, 64))
              
              # 定義輸入輸出維度映射
              tb_graph.new_input(input, (-1, -1, -1), 1, True)  # 輸入張量
              tb_graph.new_input(weight_norm, (-1, -1, -1), 0, True)  # 歸一化權重
              tb_graph.new_input(weight_linear, (0, -1, -1), 1, True)  # 線性層權重
              tb_graph.new_input(output, (1, -1, -1), -1, True)  # 輸出張量
              
              # 關聯張量與線程塊圖
              self.kn_graph.customized([input, weight_norm, weight_linear, output], tb_graph)
              
              # 注冊RMS歸一化+線性層任務
              self.kn_graph.register_task(tb_graph, "rmsnorm_linear")
      
          def attention_layer(
              self,
              input: DTensor,  # 輸入張量 (batch_size, fused_outdim / world_size)
              k_cache: DTensor,  # K緩存 (batch_size, seq_len, kv_heads, head_dim)
              v_cache: DTensor,  # V緩存 (batch_size, seq_len, kv_heads, head_dim)
              q_norm: DTensor,  # Q歸一化權重 (可選)
              k_norm: DTensor,  # K歸一化權重 (可選)
              cos_pos_embed: DTensor,  # 余弦位置編碼 (可選)
              sin_pos_embed: DTensor,  # 正弦位置編碼 (可選)
              output: DTensor,  # 輸出張量 (batch_size, hidden_size / world_size)
              grid_dim: tuple,  # CUDA網格維度
              block_dim: tuple,  # CUDA塊維度
          ):
              """
              定義注意力層計算,支持 rotary 位置編碼與 Q/K 歸一化。
              
              參數:
                  input: 輸入張量(2D)
                  k_cache: 鍵緩存張量(4D)
                  v_cache: 值緩存張量(4D)
                  q_norm: Q歸一化權重(可選,1D)
                  k_norm: K歸一化權重(可選,1D)
                  cos_pos_embed: 余弦位置編碼(可選,2D)
                  sin_pos_embed: 正弦位置編碼(可選,2D)
                  output: 輸出張量(2D)
                  grid_dim: CUDA kernel的網格維度
                  block_dim: CUDA kernel的塊維度
              說明:
                  自動檢測是否啟用 rotary 編碼與 Q/K 歸一化,動態調整計算邏輯
              """
              # 校驗輸入輸出張量維度
              assert input.num_dims == 2  # (batch_size, fused_outdim / world_size)
              assert output.num_dims == 2  # (batch_size, hidden_size / world_size)
              assert k_cache.num_dims == 4  # (batch_size, seq_len, kv_heads, head_dim)
              assert v_cache.num_dims == 4  # (batch_size, seq_len, kv_heads, head_dim)
              
              # 提取注意力頭相關參數
              head_dim = k_cache.dim(3)  # 頭維度
              num_kv_heads = k_cache.dim(2)  # KV頭數量
              num_q_heads = output.dim(1) // head_dim  # Q頭數量
              
              # 檢測是否啟用 rotary 位置編碼
              rotary_embed = 0
              if cos_pos_embed is not None or sin_pos_embed is not None:
                  assert cos_pos_embed.num_dims == 2  # (seq_len, head_dim)
                  assert sin_pos_embed.num_dims == 2  # (seq_len, head_dim)
                  assert cos_pos_embed.dim(1) == head_dim
                  assert sin_pos_embed.dim(1) == head_dim
                  rotary_embed = 1  # 標記啟用rotary編碼
              
              # 檢測是否啟用Q/K歸一化
              qk_norm = 0
              if q_norm is not None or k_norm is not None:
                  assert q_norm.num_dims == 1  # (head_dim)
                  assert k_norm.num_dims == 1  # (head_dim)
                  qk_norm = 1  # 標記啟用Q/K歸一化
                  assert q_norm.dim(0) == head_dim
                  assert k_norm.dim(0) == head_dim
              
              # 注意力層參數列表
              params = [num_q_heads, num_kv_heads, qk_norm, rotary_embed]
              
              # 創建線程塊圖
              tb_graph = TBGraph(CyTBGraph(grid_dim, block_dim, 1, 64))
              
              # 定義輸入輸出維度映射
              tb_graph.new_input(input, (0, 1, -1), -1, True)  # 輸入張量
              tb_graph.new_input(k_cache, (0, 2, -1), 1, True)  # K緩存
              tb_graph.new_input(v_cache, (0, 2, -1), 1, True)  # V緩存
              tb_graph.new_input(q_norm, (-1, -1, -1), -1, True)  # Q歸一化權重
              tb_graph.new_input(k_norm, (-1, -1, -1), -1, True)  # K歸一化權重
              tb_graph.new_input(cos_pos_embed, (-1, -1, -1), -1, True)  # 余弦位置編碼
              tb_graph.new_input(sin_pos_embed, (-1, -1, -1), -1, True)  # 正弦位置編碼
              tb_graph.new_input(output, (0, 1, -1), -1, True)  # 輸出張量
              
              # 關聯所有張量與線程塊圖
              self.kn_graph.customized(
                  [
                      input,
                      k_cache,
                      v_cache,
                      q_norm,
                      k_norm,
                      cos_pos_embed,
                      sin_pos_embed,
                      output,
                  ],
                  tb_graph,
              )
              
              # 注冊注意力層任務,附加參數
              self.kn_graph.register_task(tb_graph, "attention", params)
      

      0x04 編譯

      persistent_kernel.py的compile 函數主要功能是將定義好的內核圖(kernel graph)編譯成可執行的 CUDA 代碼,并生成一個 Python 共享庫(.so 文件),以便在 Python 環境中調用執行,具體如下:

      • 生成任務圖和 CUDA 代碼。

        • 調用 self.kn_graph.generate_task_graph 方法,基于當前定義的內核圖(KNGraph)生成任務圖(task graph)和對應的 CUDA 代碼。這一步會根據圖中的操作(如矩陣乘法、元素級運算等)生成優化后的 CUDA 實現。
      • 準備編譯環境。

        • 創建臨時目錄用于存放生成的代碼文件和編譯產物。
        • 將生成的 CUDA 代碼寫入 .cu 文件。
        • 將任務圖的 JSON 表示寫入文件,便于調試或后續分析。
      • 配置編譯參數

        • 獲取 CUDA 編譯器(nvcc)路徑。
        • 確定 Python 頭文件路徑,以便生成的庫可以與 Python 交互。
        • 獲取 Mirage 框架的頭文件和依賴庫路徑。
        • 如果使用 NVSHMEM(多 GPU 通信庫),則還需要配置 NVSHMEM 和 MPI 的頭文件及庫路徑。
      • 執行編譯

        • 構建完整的 nvcc 編譯命令,包括源文件、包含路徑、編譯選項、目標架構等。
        • 調用 subprocess.check_call 執行編譯命令,生成一個 Python 可導入的共享庫(.so 文件)。
      • 加載編譯結果

        • 使用 importlib.util.spec_from_file_location 和 importlib.util.module_from_spec動態加載編譯生成的 .so 文件作為 Python 模塊。
        • 從加載的模塊中獲取初始化、執行和終結函數(init_func, launch_func, finalize_func),并保存為 PersistentKernel 對象的成員變量,供后續調用。

      流程圖如下:

      MPK-3-3

      具體代碼如下:

      def compile(
          self,
          **kwargs,
      ):      
          # 從關鍵字參數中獲取輸出目錄,默認為None
          output_dir = kwargs.get("output_dir", None)
          # 獲取Mirage相關的核心路徑(根目錄、包含目錄、依賴目錄)
          MIRAGE_ROOT, INCLUDE_PATH, DEPS_PATH = get_key_paths()
          # 創建臨時目錄用于存放編譯過程中的中間文件
          tempdir_obj = tempfile.TemporaryDirectory()
          tempdir = tempdir_obj.name
          # 生成任務圖:根據GPU數量和當前GPU ID劃分計算任務
          results = self.kn_graph.generate.generate_task_graph(num_gpus=self.world_size, my_gpu_id=self.mpi_rank)
      
          # 定義CUDA代碼和編譯產物的臨時路徑
          cuda_code_path = os.path.join(tempdir, "test.cu")  # 生成的CUDA源代碼路徑
          so_path = os.path.join(tempdir, "test.cpython-38-x86_64-linux-gnu.so")  # 編譯后的的共享庫路徑
          # 定義任務圖JSON文件的臨時路徑
          json_file_path = os.path.join(tempdir, "task_graph.json")
          # 將任務圖數據寫入JSON文件
          with open(json_file_path, "w") as f:
              f.write(results["json_file"])
          # 將生成的CUDA代碼與硬編碼補充內容合并后寫入文件
          with open(cuda_code_path, "w") as f:
              f.write(results["cuda_code"] + HARD_CODE)
              
          # 若指定了輸出目錄,將生成的CUDA代碼和JSON文件復制到該目錄
          if output_dir is not None:
              os.makedirs(output_dir, exist_ok=True)  # 確保輸出目錄存在(已存在則不報錯)
              shutil.copy(cuda_code_path, os.path.join(output_dir, "test.cu"))  # 復制CUDA代碼
              shutil.copy(json_file_path, os.path.join(output_dir, "task_graph.json"))  # 復制任務圖JSON
      
          # 檢查nvcc(CUDA編譯器)是否存在
          cc = shutil.which("nvcc")
          if cc is None:
              # 若未找到nvcc,拋出運行時錯誤提示用戶安裝CUDA
              raise RuntimeError(
                  "nvcc not found. Please make sure you have installed CUDA."
              )
          # 確定Python的默認安裝路徑方案(適配不同Python版本的API差異)
          # Python 3.10及以上版本使用get_default_scheme方法
          if hasattr(sysconfig, "get_default_scheme"):
              scheme = sysconfig.get_default_scheme()
          else:
              # 舊版本Python使用內部方法_get_default_scheme
              scheme = sysconfig._get_default_scheme()
          # 修正Debian系統中的路徑方案,確保與系統Python兼容
          if scheme == "posix_local":
              scheme = "posix_prefix"
          # 獲取Python的頭文件包含目錄(用于編譯時鏈接Python庫)
          py_include_dir = sysconfig.get_paths(scheme=scheme)["include"]
      
          # 從環境變量中獲取Mirage的安裝路徑(若已設置)
          if "MIRAGE_HOME" in os.environ:
              MIRAGE_HOME_PATH = os.environ.get("MIRAGE_HOME")
      
          # 初始化NVSHMEM和MPI相關的路徑變量(用于分布式通信)
          NVSHMEM_INC_PATH = None  # NVSHMEM頭文件目錄
          NVSHMEM_LIB_PATH = None  # NVSHMEM庫文件目錄
          MPI_INC_PATH = None  # MPI頭文件目錄
          MPI_LIB_PATH = None  # MPI庫文件目錄
          # 若啟用NVSHMEM(NVIDIA共享內存庫),配置其相關路徑
          if self.use_nvshmem:
              # 配置NVSHMEM頭文件路徑
              if "NVSHMEM_INC_PATH" in os.environ:
                  # 優先使用環境變量中指定的路徑
                  NVSHMEM_INC_PATH = os.environ.get("NVSHMEM_INC_PATH")
                  header_file_path = os.path.join(NVSHMEM_INC_PATH, "nvshmem.h")
              else:
                  # 未指定則使用默認路徑
                  NVSHMEM_INC_PATH = "/usr/include/nvshmem_12/"
                  header_file_path = os.path.join(NVSHMEM_INC_PATH, "nvshmem.h")
              # 配置NVSHMEM庫文件路徑
              if "NVSHMEM_LIB_PATH" in os.environ:
                  NVSHMEM_LIB_PATH = os.environ.get("NVSHMEM_LIB_PATH")
                  lib_file_path = os.path.join(NVSHMEM_LIB_PATH, "libnvshmem.a")
              else:
                  NVSHMEM_LIB_PATH = "/usr/lib/x86_64-linux-gnu/"
                  lib_file_path = os.path.join(NVSHMEM_LIB_PATH, "libnvshmem.a")
              # 配置MPI頭文件路徑(NVSHMEM依賴MPI)
              if "MPI_INC_PATH" in os.environ:
                  MPI_INC_PATH = os.environ.get("MPI_INC_PATH")
                  header_file_path = os.path.join(MPI_INC_PATH, "mpi.h")
              else:
                  MPI_INC_PATH = "/usr/include/"
                  header_file_path = os.path.join(MPI_INC_PATH, "mpi.h")
              # 配置MPI庫文件路徑
              if "MPI_LIB_PATH" in os.environ:
                  MPI_LIB_PATH = os.environ.get("MPI_LIB_PATH")
                  lib_file_path = os.path.join(MPI_LIB_PATH, "libmpi.so")
              else:
                  NVSHMEM_LIB_PATH = "/usr/lib/"
                  lib_file_path = os.path.join(MPI_LIB_PATH, "libmpi.so")
          # 獲取當前GPU的計算能力(如86對應A100,75對應T4等)
          target_cc = (
              torch.cuda.get_device_properties(0).major * 10
              + torch.cuda.get_device_properties(0).minor
          )
      
          # 生成CUDA編譯命令
          cc_cmd = get_compile_command(
              target_cc=target_cc,  # GPU計算能力
              cc=cc,  # nvcc編譯器路徑
              file_name=cuda_code_path,  # 輸入的CUDA源代碼
              py_include_dir=py_include_dir,  # Python頭文件目錄
              mirage_home_path=MIRAGE_HOME_PATH,  # Mirage根目錄
              mirage_inc_path=INCLUDE_PATH,  # Mirage頭文件目錄
              mirage_deps_path=DEPS_PATH,  # Mirage依賴目錄
              nvshmem_inc_path=NVSHMEM_INC_PATH,  # NVSHMEM頭文件目錄
              nvshmem_lib_path=NVSHMEM_LIB_PATH,  # NVSHMEM庫目錄
              mpi_inc_path=MPI_INC_PATH,  # MPI頭文件目錄
              mpi_lib_path=MPI_LIB_PATH,  # MPI庫目錄
              py_so_path=so_path,  # 輸出的共享庫路徑
              profiling=True if self.profiler_tensor is not None else False,  # 是否啟用性能分析
              use_nvshmem=self.use_nvshmem,  # 是否使用NVSHMEM
              num_workers=self.num_workers,  # 工作線程數量
              num_local_schedulers=self.num_local_schedulers,  # 本地調度器數量
              num_remote_schedulers=self.num_remote_schedulers,  # 遠程調度器數量
          )
          # 執行編譯命令,生成共享庫
          subprocess.check_call(cc_cmd)
      
          # 動態導入編譯生成的共享庫
          import importlib.util
          # 創建模塊規格:指定模塊名稱和共享庫路徑
          spec = importlib.util.spec_from_file_location("__mirage_launcher", so_path)
          # 從規格創建模塊
          mod = importlib.util.module_from_spec(spec)
          # 執行模塊加載
          spec.loader.exec_module(mod)
          # 綁定模塊中的核心函數(初始化、啟動、結束)
          self.init_func = getattr(mod, "init_func")
          self.launch_func = getattr(mod, "launch_func")
          self.finalize_func = getattr(mod, "finalize_func")
          # 打印編譯完成提示
          print("Finished megakernel compilation...")
      
          # 收集元數據張量的內存地址指針
          meta_tensors_ptr = [tensor.data_ptr() for tensor in self.meta_tensors]
          # 獲取性能分析緩沖區的內存地址(若啟用性能分析)
          profiler_buffer_ptr = (
              self.profiler_tensor.data_ptr() if self.profiler_tensor is not None else 0
          )
          # 調用初始化函數,傳入必要的參數
          self.init_func(
              meta_tensors_ptr,  # 元數據張量指針列表
              profiler_buffer_ptr,  # 性能分析緩沖區指針
              self.mpi_rank,  # 當前MPI進程編號
              self.num_workers,  # 工作線程數量
              self.num_local_schedulers,  # 本地調度器數量
              self.num_remote_schedulers,  # 遠程調度器數量
              self.max_seq_length,  # 最大序列長度
              self.eos_token_id,  # 結束符token ID
          )
      
          # 標記編譯完成狀態
          self._is_compiled = True
      

      總的來說,compile 函數的作用是將用戶通過 PersistentKernel API 定義的計算圖轉換為高度優化的 CUDA 代碼,并將其編譯為可在當前系統上運行的 Python 模塊,從而實現高性能的 GPU 計算。編譯成功后,用戶可以通過調用 init_func, launch_func, finalize_func 來初始化、執行和清理內核。

      0x05 執行

      persistent_kernel.py調用call()方法啟動內核執行。

          def __call__(self, **kwargs):
              self.launch_func()
              if self.profiler_tensor is not None:
                  from .profiler_persistent import export_to_perfetto_trace
      
                  export_to_perfetto_trace(
                      self.profiler_tensor, f"mirage_{self.mpi_rank}.perfetto-trace"
                  )
      

      launch_func()函數會調用launch_persistent_kernel()來啟動內核。

      static PyObject *launch_func(PyObject *self, PyObject *args) {
        launch_persistent_kernel();
      
        Py_RETURN_NONE;
      }
      

      0xFF 參考

      如何評價CMU將LLM轉化為巨型內核的Mirage Persistent Kernel(MPK)工作?

      Mirage: A Multi-Level Superoptimizer for Tensor Programs 簡記 塵伊光

      OSDI2025論文筆記:Mirage: A Multi-Level Superoptimizer for Tensor Programs 畫餅充饑

      Mirage: A Compiler for High-Performance Tensor Programs on GPUs

      https://mirage-project.readthedocs.io/en/latest/mugraph.html

      https://mirage-project.readthedocs.io/en/latest/transpiler.html

      https://zhihaojia.medium.com/compiling-llms-into-a-megakernel-a-path-to-low-latency-inference-cf7840913c17

      舍棄CUDA編程!CMU等用代碼將LLM編譯成巨型內核,推理延遲降6.7倍 機器之心Pro

      posted @ 2025-10-29 21:12  羅西的思考  閱讀(56)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 九九热中文字幕在线视频| 国产av一区二区亚洲精品| 国产精品熟女一区二区不卡| 日韩免费无码视频一区二区三区| 色吊丝永久性观看网站| 久久精品免视看国产成人| 欧美日韩中文字幕视频不卡一二区| 四虎影视永久无码精品| 国产成人精品一区二区三区无码| 日本激情久久精品人妻热| 久久精品99国产精品亚洲| 欧美性69式xxxx护士| 国产中文字幕精品在线| 日本一本无道码日韩精品| 人妻丝袜无码专区视频网站| 国产AV无码专区亚洲AWWW| 国产精品亚洲二区亚瑟| 欧美裸体xxxx极品| 国产中文三级全黄| 性按摩玩人妻hd中文字幕| 国产一区二区三区九九视频| 久久精品国产亚洲av麻豆长发| 日韩少妇内射免费播放 | 国产精品∧v在线观看| 熟女精品色一区二区三区| 成人精品视频一区二区三区| 国产精品午夜福利资源| 日日摸夜夜添夜夜添国产三级| 亚洲自偷自拍另类小说| 国产三级a三级三级| 人妻在线无码一区二区三区| 国产成人综合久久亚洲精品| 精品无人区卡一卡二卡三乱码| 美女自卫慰黄网站| 少妇激情一区二区三区视频小说| 色狠狠色噜噜AV一区| 镇坪县| 国产激情一区二区三区不卡| 亚洲www永久成人网站| 久久精品女人天堂av| 精品午夜福利在线视在亚洲|