深入 NVIDIA cuDNN Graph API:透過 cuDNN 前端實現融合、自動調優與計畫重用
In this tutorial, we work through the cuDNN Frontend‘s graph API from below the framework: we describe a computation as a graph of operations, let cuDNN pick an engine to run it, and then take control of that choice ourselves.
Every kernel we build here is expressed the same way: we declare tensors by their dimensions and strides, chain operations onto them, run the five-step build pipeline of validate, build operation graph, create execution plans, check support, and build plans, and then execute against a variant pack of pointers.
We run it all on a single Colab GPU, checking each result against a PyTorch reference so we can see both that the fusion is correct and what it costs.
The topics build on each other, moving from a single fused convolution to autotuning across engine configs, FP8-style epilogues, attention, plan serialization, dynamic shapes, and CUDA graph capture.
Copy CodeCopiedUse a different Browserimport os import sys import glob import math import time import ctypes import traceback import subprocess RESULTS = {} def banner(title): print("\n" + "=" 78) print(title) print("=" 78) def section(name): def wrap(fn): def run(a, kw): banner(name) try: out = fn(a, kw) RESULTS[name] = out if isinstance(out, str) else "ok" return out except Exception as e: RESULTS[name] = f"SKIPPED / FAILED -> {type(e).
name}: {e}" print(f"\n[!] {name} did not complete: {type(e).name}: {e}") traceback.printexc(limit=3) return None return run return wrap banner("0.Install nvidia-cudnn-frontend and locate libcudnn") subprocess.run( [sys.
executable, "-m", "pip", "install", "-q", "nvidia-cudnn-frontend"], check=True, ) import torch assert torch.cuda.isavailable(), "No GPU.Runtime -> Change runtime type -> GPU." torch.backends.cudnn.enabled = True = torch.nn.functional.conv2d( torch.randn(1, 1, 8, 8, device="cuda"), torch.
randn(1, 1, 3, 3, device="cuda") ) torch.cuda.synchronize() try: import nvidia.cudnn libdir = os.path.join(os.path.dirname(nvidia.cudnn.file), "lib") os.environ["CUDNNPATH"] = os.path.dirname(nvidia.cudnn.file) os.environ["LDLIBRARYPATH"] = libdir + ":" + os.environ.
get("LDLIBRARYPATH", "") for so in sorted(glob.glob(os.path.join(libdir, "libcudnn.so"))): try: ctypes.CDLL(so, mode=ctypes.
RTLDGLOBAL) except OSError: pass except Exception as e: print(f" (no pip cuDNN package found, relying on system cuDNN: {e})") import cudnn print(" cuDNN frontend imported successfully.") banner("1.Environment") DEV = torch.device("cuda") MAJOR, MINOR = torch.cuda.
getdevicecapability() SM = MAJOR 10 + MINOR CUDNNVER = cudnn.backendversion() print(f" GPU : {torch.cuda.getdevicename(0)}") print(f" Compute capability : sm{SM}") print(f" Torch / CUDA : {torch.version} / {torch.version.
cuda}") print(f" cuDNN backend : {CUDNNVER}") try: print(f" cuDNN version str : {cudnn.backendversionstring()}") except Exception: pass DTYPE = torch.bfloat16 if SM >= 80 else torch.float16 HASSDPA = SM >= 80 print(f" Working dtype : {DTYPE}") print(f" Fused SDPA usable : {HASSDPA}") HANDLE = cudnn.
createhandle() TORCH2CUDNN = { torch.float16: cudnn.datatype.HALF, torch.bfloat16: cudnn.datatype.BFLOAT16, torch.float32: cudnn.datatype.FLOAT, torch.int32: cudnn.datatype.INT32, torch.int64: cudnn.datatype.INT64, torch.int8: cudnn.datatype.INT8, torch.uint8: cudnn.datatype.
UINT8, } def tensorof(graph, t, name): return graph.tensor( name=name, dim=list(t.size()), stride=list(t.stride()), datatype=TORCH2CUDNN[t.dtype], ) def scalarof(graph, name): return graph.tensor( name=name, dim=[1, 1, 1], stride=[1, 1, 1], datatype=cudnn.datatype.
FLOAT, ispassbyvalue=True, ) def build(graph, heur=None, policy=None): heur = heur or [cudnn.heurmode.A, cudnn.heurmode.FALLBACK] graph.validate() graph.buildoperationgraph() graph.createexecutionplans(heur) graph.checksupport() if policy is None: graph.buildplans() else: graph.
buildplans(policy) return graph def workspacefor(graph): n = graph.getworkspacesize() return torch.empty(max(n, 1), device=DEV, dtype=torch.uint8) def bench(fn, warmup=10, iters=50): for in range(warmup): fn() torch.cuda.synchronize() s, e = torch.cuda.Event(True), torch.cuda.Event(True) s.
record() for in range(iters): fn() e.record() torch.cuda.synchronize() return s.elapsedtime(e) / iters def tflops(flops, ms): return flops / (ms 1e-3) / 1e12 def report(tag, ms, flops=None): extra = f" ({tflops(flops, ms):7.2f} TFLOP/s)" if flops else "" print(f" {tag:<34s} {ms:8.
3f} ms{extra}") We start by installing nvidia-cudnn-frontend and solving the problem that trips up most first runs: making libcudnn.so visible to the frontend’s dynamic loader.
We force PyTorch to load its bundled cuDNN first and then preload the shared objects explicitly, so the frontend’s own dlopen resolves against a library already resident in the process.
We then report the compute capability, pick bfloat16 or float16 accordingly, create the cuDNN handle, and define the helpers for tensor description, graph building, workspace allocation, and event-based benchmarking that the rest of the notebook reuses.
Copy CodeCopiedUse a different BrowserN, C, H, W = 32, 128, 56, 56 K, R, S = 256, 3, 3 PAD, STR, DIL = 1, 1, 1 P = (H + 2 PAD - DIL (R - 1) - 1) // STR + 1 Q = (W + 2 PAD - DIL (S - 1) - 1) // STR + 1 CONVFLOPS = 2 N K P Q C R S CONVSTATE = {} @section("2.
Fused Conv -> Bias -> ReLU") def convfusion(): x = torch.randn(N, C, H, W, device=DEV, dtype=DTYPE).to(memoryformat=torch.channelslast) w = torch.randn(K, C, R, S, device=DEV, dtype=DTYPE).to(memoryformat=torch.channelslast) b = torch.randn(1, K, 1, 1, device=DEV, dtype=DTYPE) y = torch.
empty(N, K, P, Q, device=DEV, dtype=DTYPE).to(memoryformat=torch.channelslast) g = cudnn.pygraph( handle=HANDLE, name="convbiasrelu", iodatatype=TORCH2CUDNN[DTYPE], intermediatedatatype=cudnn.datatype.FLOAT, computedatatype=cudnn.datatype.
FLOAT, ) X = tensorof(g, x, "X") Wt = tensorof(g, w, "W") Bt = tensorof(g, b, "bias") conv = g.convfprop( image=X, weight=Wt, padding=[PAD, PAD], stride=[STR, STR], dilation=[DIL, DIL], computedatatype=cudnn.datatype.FLOAT, ) biased = g.bias(input=conv, bias=Bt) Y = g.relu(input=biased) Y.
setoutput(True).setdatatype(TORCH2CUDNN[DTYPE]) Y.setdim(list(y.size())).setstride(list(y.stride())) t0 = time.perfcounter() build(g) buildms = (time.perfcounter() - t0) 1e3 ws = workspacefor(g) pack = {X: x, Wt: w, Bt: b, Y: y} g.execute(pack, ws) torch.cuda.synchronize() ref = torch.relu(torch.nn.
functional.conv2d(x, w, bias=b.flatten(), padding=PAD)) err = (y.float() - ref.float()).abs().max().item() scale = ref.float().abs().max().item() print(f" problem : N{N} C{C} {H}x{W} -> K{K} {R}x{S} ({DTYPE})") print(f" build : {buildms:.1f} ms workspace: {ws.numel()/1024:.
1f} KiB") print(f" max |err|: {err:.4f} (ref max {scale:.2f}, rel {err/max(scale,1e-9):.2e})") assert err / max(scale, 1e-9) < 5e-2, "numerical mismatch vs PyTorch" mscudnn = bench(lambda: g.execute(pack, ws)) mstorch = bench(lambda: torch.relu( torch.nn.functional.conv2d(x, w, bias=b.
flatten(), padding=PAD))) print() report("cuDNN FE (single fused kernel)", mscudnn, CONVFLOPS) report("PyTorch (conv+bias, then relu)", mstorch, CONVFLOPS) print(f" speedup: {mstorch/mscudnn:.2f}x") CONVSTATE.update(graph=g, pack=pack, ws=ws, x=x, w=w, b=b, y=y) return f"{mscudnn:.
3f} ms, {tflops(CONVFLOPS, mscudnn):.1f} TFLOP/s" convfusion() We build our first graph, a convolution followed by a bias add and a ReLU, all fused into a single kernel.
We keep every tensor in channels_last because that is what gives cuDNN the NHWC strides its tensor-core engines want, and we pin the output dimensions and strides explicitly so the result is written back in the same layout.We validate the output against torch.nn.functional.
conv2d, then benchmark the fused graph against PyTorch running the convolution and activation as separate kernels.Copy CodeCopiedUse a diffe
Related
相關文章

達卯科技算電協同2.0平臺入選2026國際數字能源展重大成果發佈
成果中唯一聚焦算電協同全鏈路運營的AI技術產品 9月15日-17日,2026能源綠色發展大會・國際數字能源展在深圳舉辦。展會首次以“一會一展”深度融合模式打造全球數字能源產業盛會,集中發佈近百項前沿創新成果。達卯科技自主研發的「算電協同2.0平臺・AIDC綠電直連能源運營操作系統」成功入選重大成果發佈,也是成果中唯一聚焦算電協同全鏈路運營的AI技術產品。

消息稱特斯拉針對 Optimus 機器人業務啟動量產審廠,多家供應鏈企業回應
作者:清源 責編:清源 評論: 感謝網友 麻辣清補涼、不一樣的體驗 的線索投遞!9 月 18 日消息,日前,21 世紀經濟報道援引產業鏈人士消息稱,特斯拉相關團隊已於 9 月 16 日落地寧波,並於 17 日開啟新一輪針對旗下機器人業務的量產審廠。

小鵬要把賣車和賣技術一起推向全球
王小娟 發表於 2026年09月18日 14:05 摘要:技術合作再尋新客戶。9月17日晚,小鵬集團董事長、CEO何小鵬談起G9L的價格,說自己和總裁王鳳英曾在會議室裡反覆爭論。幾小時前,這款車剛以23.18萬元的 限時起售價上市,較8月公佈的預售起售價低了2.

Claude“主導”Anthropic 26%的AI研發、3萬Agent同時運行:當AI開始“造AI”,頭部公司RSI路線正在分化
根據報導,人工智慧領域近期出現一項值得關注的動向:Anthropic 的 AI 模型 Claude 在其內部研發工作中扮演了主導角色,佔據該公司約 26% 的 AI 研發比例,同時有高達 3 萬個 Agent 在同一時間並行運作。這項數據反映出 AI 開始「製造 AI」的趨勢正在加速,而頭部公司在遞歸自我改進(RSI)路線上的分化也愈發明顯。 Claude 不再只是對外服務的產品,而是成為 Anthropic 內部研發流程的核心引擎。

智譜實現RSI最小閉環,A社:我來監督
智譜AI近日對外宣布,已在遞歸自我改進(Recursive Self-Improvement,簡稱RSI)領域取得關鍵技術突破,成功實現業界首個「最小閉環」系統。與此同時,被業內簡稱為「A社」的AI安全研究機構同步表態,將以第三方監督角色介入該系統的測試與驗證流程,確保技術發展符合倫理與安全規範。 所謂的最小閉環,指的是系統能在不依賴外部人工反饋的情況下,自主完成從自我評估、參數調整到性能驗證的完整循環。

傳聞四起,人形機器人IPO審核收緊?
近期市場傳出多項風聲,指稱人形機器人領域的首次公開募股(IPO)審核可能出現收緊趨勢。雖然官方尚未發布明確指引,但這波傳言已在投資人與業界之間引發討論,不少人開始關注監管層是否會對這類新興科技公司的上市門檻提出更高要求。 與此同時,宇樹科技在資本市場上的戲劇性波動,也被視為影響整體情緒的關鍵變數。