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()方法或者自動析構。
具體如下圖所示。

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等)定義計算圖。簡易流程如下:

對應的代碼舉例如下:
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 對象的成員變量,供后續調用。
流程圖如下:

具體代碼如下:
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
浙公網安備 33010602011771號