化與FlashAttention內(nèi)存調(diào)度實(shí)戰(zhàn))
1. 這25道題不是考你背了多少API而是看你能不能把GPU當(dāng)“工地”來管我?guī)н^三屆AI Infra方向的校招面試也幫團(tuán)隊(duì)篩過上百份CUDA方向的簡歷。每次出題前我都會(huì)先問自己一個(gè)問題如果這個(gè)人明天就要接手我們線上推理服務(wù)的Kernel優(yōu)化任務(wù)他第一周能不能獨(dú)立定位到一個(gè)歸約操作的bank conflict能不能看懂FlashAttention里那個(gè)shared memory分塊調(diào)度的邊界條件能不能在WSL2里把CUDA 12.8和PyTorch 2.3.1的ABI對(duì)齊這25道題就是從這個(gè)真實(shí)場景里長出來的。它不考你“__syncthreads()的作用是什么”而是考你“為什么在reduce_max_kernel里用warp-level reduction比block-level reduction快37%——這個(gè)數(shù)字是怎么算出來的”。它不問“FlashAttention的QKV分塊邏輯”而是讓你手畫一張圖當(dāng)sequence length2048、head_dim64、block_size128時(shí)shared memory里到底存了幾塊Q、幾塊K、幾塊V每塊占多少bytebank conflict發(fā)生在哪一行。很多人刷完《CUDA C Programming Guide》覺得穩(wěn)了結(jié)果一上來就被第3題卡住“請(qǐng)寫出一個(gè)能正確處理任意size輸入非2的冪的warp shuffle reduce_sum并解釋__shfl_sync(0xFFFFFFFF, val, 1)中mask參數(shù)為什么不能寫成0xFFFF”。這不是刁難是告訴你生產(chǎn)環(huán)境里沒有“剛好是1024”的tensor你的kernel必須扛得住real-world data的毛刺。關(guān)鍵詞里沒寫“面試”但標(biāo)題里“AI Infra 面試”四個(gè)字已經(jīng)劃出了戰(zhàn)場邊界——這里不歡迎純理論派只接納能把CUDA文檔讀成施工圖紙的人。下面這25題每一題背后都對(duì)應(yīng)著我們線上服務(wù)踩過的坑、壓測時(shí)掉過的幀、深夜debug時(shí)抓過的頭發(fā)?,F(xiàn)在我把它們攤開連同當(dāng)時(shí)怎么想、怎么試、怎么改一起給你講透。2. 歸約Reduction從教科書公式到GPU寄存器級(jí)實(shí)操2.1 教科書里的歸約 vs. GPU上的歸約差的不是算法是內(nèi)存墻幾乎所有CUDA入門教程都用一個(gè)經(jīng)典例子開場對(duì)一個(gè)長度為N的float數(shù)組求和。教科書偽代碼通常是sum 0 for i in range(N): sum arr[i]然后告訴你“并行化就是每個(gè)thread處理一個(gè)元素”。但現(xiàn)實(shí)里當(dāng)你真把這段邏輯寫成kernel__global__ void naive_reduce(float* input, float* output, int n) { int tid blockIdx.x * blockDim.x threadIdx.x; if (tid n) { atomicAdd(output, input[tid]); // 錯(cuò)大錯(cuò) } }你會(huì)發(fā)現(xiàn)哪怕N65536這個(gè)kernel的吞吐量還不到峰值帶寬的5%。問題不在算法而在內(nèi)存訪問模式和同步開銷。教科書歸約假設(shè)內(nèi)存是“瞬時(shí)可達(dá)”的而GPU的L2 cache延遲是400 cyclesglobal memory延遲是800 cycles。atomicAdd本質(zhì)是“讀-改-寫”三步原子操作每次都要鎖住整個(gè)cache line64 byte1024個(gè)thread同時(shí)爭搶同一地址性能直接崩盤。提示面試官問“為什么不用atomicAdd”真正想聽的不是“因?yàn)槁倍恰耙驗(yàn)樗巡⑿杏?jì)算變成了串行內(nèi)存競爭違背了SIMT架構(gòu)的設(shè)計(jì)初衷”。2.2 四層歸約結(jié)構(gòu)從thread到warp再到block每一層都在對(duì)抗硬件限制我們線上推理服務(wù)的logit歸約kernel采用的是四級(jí)結(jié)構(gòu)thread → warp → block → host每一級(jí)解決一類硬件瓶頸層級(jí)數(shù)據(jù)規(guī)模關(guān)鍵技術(shù)硬件約束應(yīng)對(duì)Thread內(nèi)1個(gè)float寄存器累加避免local memory溢出寄存器最快Warp內(nèi)32個(gè)float__shfl_down_sync消除shared memory bank conflictwarp shuffle無bank沖突Block內(nèi)≤1024個(gè)floatshared memory分塊__syncthreads解決global memory帶寬瓶頸shared memory帶寬是global的10倍Host端多block結(jié)果cudaMemcpyAsyncCPU歸約規(guī)避PCIe帶寬墻PCIe 4.0 x16帶寬≈16GB/s遠(yuǎn)低于HBM2的2TB/s重點(diǎn)說warp級(jí)歸約。__shfl_down_sync(mask, val, delta)的delta參數(shù)決定了數(shù)據(jù)在warp內(nèi)32個(gè)lane間的平移距離。比如float warp_sum val; for (int offset 16; offset 0; offset / 2) { warp_sum __shfl_down_sync(0xFFFFFFFF, warp_sum, offset); }這里offset16意味著lane0和lane16交換lane1和lane17交換……最終lane0拿到warp內(nèi)32個(gè)thread的sum。關(guān)鍵點(diǎn)在于mask必須是0xFFFFFFFF全1否則warp內(nèi)部分lane會(huì)被屏蔽導(dǎo)致歸約結(jié)果錯(cuò)誤。很多候選人寫成0xFFFF以為“16位夠了”卻忘了warp有32個(gè)lane——這是典型的“紙上談兵”式錯(cuò)誤。2.3 非2的冪尺寸的歸約padding不是偷懶是避免分支預(yù)測失敗真實(shí)模型輸出的token數(shù)往往是128、256、512但也有73、197、1023這種“毛刺尺寸”。如果強(qiáng)行用2的冪歸約邏輯// 錯(cuò)誤示范用if判斷越界 if (tid n tid stride n) { // 分支預(yù)測失敗 temp input[tid] input[tid stride]; }GPU的branch divergence會(huì)讓warp內(nèi)所有l(wèi)ane等最慢的路徑執(zhí)行完性能損失高達(dá)50%。正確做法是padding mask__global__ void padded_reduce(float* input, float* output, int n) { extern __shared__ float sdata[]; int tid threadIdx.x; int idx blockIdx.x * blockDim.x threadIdx.x; // padding超出n的部分用0填充 float val (idx n) ? input[idx] : 0.0f; sdata[tid] val; __syncthreads(); // 歸約時(shí)用mask控制有效lane數(shù) for (int s blockDim.x / 2; s 0; s 1) { if (tid s (tid s) n) { // mask只對(duì)有效索引做歸約 sdata[tid] sdata[tid s]; } __syncthreads(); } if (tid 0) output[blockIdx.x] sdata[0]; }注意(tid s) n這個(gè)條件——它保證了即使blockDim.x1024而n1023最后一步s1時(shí)tid1022不會(huì)去讀sdata[1023]越界。這個(gè)細(xì)節(jié)決定了kernel在邊緣case下的穩(wěn)定性。2.4 實(shí)測對(duì)比四種歸約實(shí)現(xiàn)的吞吐量與功耗曲線我們?cè)贏100上實(shí)測了四種歸約方案N65536float32方案吞吐量 (GB/s)能效比 (GFLOPS/W)L2 cache命中率典型適用場景Naive atomicAdd0.81.212%debug階段快速驗(yàn)證Shared memory單級(jí)12.48.768%小batch inferenceWarp shuffle兩級(jí)28.915.392%中等seq length≤512四級(jí)混合歸約36.218.195%大模型推理seq2048看到?jīng)]warp shuffle方案比shared memory方案快130%不是因?yàn)樗惴ǜ鼉?yōu)而是繞過了shared memory的bank conflict。A100的shared memory有32個(gè)bank當(dāng)32個(gè)thread同時(shí)訪問sdata[tid]和sdata[tid16]時(shí)恰好落在同一bankbank index address % 32造成sequential access變成sequential conflict。而warp shuffle走的是register file完全規(guī)避了bank問題。注意面試中如果被問“為什么warp shuffle比shared memory快”答“因?yàn)楦臁笔橇惴执稹耙驗(yàn)楸苊饬藄hared memory bank conflict”是及格答“因?yàn)閎ank conflict導(dǎo)致effective bandwidth下降至理論值的30%而warp shuffle利用register file的10TB/s帶寬”才是滿分。3. CUDA安裝與環(huán)境適配WSL2不是虛擬機(jī)是雙模GPU直通管道3.1 WSL2的CUDA真相它不是“Linux子系統(tǒng)”而是Windows GPU驅(qū)動(dòng)的Linux ABI兼容層很多人以為WSL2裝CUDA就是“在Linux里裝NVIDIA驅(qū)動(dòng)”這是致命誤解。WSL2本身沒有自己的GPU驅(qū)動(dòng)它通過Windows的WDDM驅(qū)動(dòng)暴露一個(gè)Linux-compatible interface。這意味著nvidia-smi在WSL2里顯示的GPU信息其實(shí)是Windows host的驅(qū)動(dòng)狀態(tài)CUDA kernel的launch、memory copy、synchronization全部由Windows NTDLL.dll和nvlddmkm.sys完成WSL2的CUDA版本必須嚴(yán)格匹配Windows host的driver version查證方法很簡單在WSL2里運(yùn)行cat /proc/driver/nvidia/version輸出類似NVRM version: NVIDIA UNIX WSL2 x86_64 535.104.05這個(gè)535.104.05就是Windows host上安裝的NVIDIA driver版本號(hào)。如果你在Windows里裝的是535.104.05那么WSL2里最高只能裝CUDA 12.2根據(jù)NVIDIA官方compatibility table。硬裝CUDA 12.8會(huì)導(dǎo)致cudaMalloc返回cudaErrorInvalidValue——不是代碼錯(cuò)是ABI不匹配。提示面試官問“WSL2如何安裝CUDA”真正想考察的是你是否理解WSL2的GPU架構(gòu)本質(zhì)。答“下載.run包安裝”是實(shí)習(xí)生水平答“先查Windows driver version再選對(duì)應(yīng)CUDA toolkit”是工程師水平答“用nvidia-container-toolkit在WSL2里跑Docker規(guī)避host driver綁定”是架構(gòu)師水平。3.2 CUDA多版本共存不是PATH切換是ABI符號(hào)表隔離線上服務(wù)常需同時(shí)跑PyTorch 1.13依賴CUDA 11.7和PyTorch 2.3依賴CUDA 12.1。很多人用export PATH/usr/local/cuda-11.7/bin:$PATH切換結(jié)果遇到ImportError: libcudnn.so.8: cannot open shared object file根本原因在于CUDA toolkit的so文件libcudart.so、libcudnn.so是通過RPATH嵌入到PyTorch binary里的。ldd torch/lib/libtorch_cuda.so | grep cudnn會(huì)顯示libcudnn.so.8 /usr/local/cuda-11.7/lib64/libcudnn.so.8 (0x00007f...)所以PATH切換無效必須用LD_LIBRARY_PATH隔離# PyTorch 1.13環(huán)境 export LD_LIBRARY_PATH/usr/local/cuda-11.7/lib64:/usr/local/cudnn-v8.5/lib64:$LD_LIBRARY_PATH python -c import torch; print(torch.__version__, torch.version.cuda) # PyTorch 2.3環(huán)境 export LD_LIBRARY_PATH/usr/local/cuda-12.1/lib64:/usr/local/cudnn-v8.9/lib64:$LD_LIBRARY_PATH python -c import torch; print(torch.__version__, torch.version.cuda)更徹底的方案是用patchelf修改binary的RPATHpatchelf --set-rpath /usr/local/cuda-12.1/lib64:/usr/local/cudnn-v8.9/lib64 torch/lib/libtorch_cuda.so這個(gè)操作要極其謹(jǐn)慎——改錯(cuò)RPATH會(huì)導(dǎo)致整個(gè)PyTorch無法加載。我們線上用Ansible playbook自動(dòng)完成每臺(tái)機(jī)器預(yù)裝兩個(gè)CUDA版本通過symbolic link/usr/local/cuda指向當(dāng)前active版本再用patchelf批量修復(fù)。3.3 CUDA 12.8 cuDNN 8.9.7新舊ABI的隱性斷裂點(diǎn)CUDA 12.8引入了新的stream-ordered memory allocatorcudaMallocAsynccuDNN 8.9.7則要求libcudnn.so.8必須導(dǎo)出cudnnSetStream符號(hào)。但某些Linux發(fā)行版如Ubuntu 22.04默認(rèn)glibc 2.35的dynamic linker在解析符號(hào)時(shí)會(huì)因symbol versioning mismatch失敗?,F(xiàn)象是import torch成功但torch.nn.functional.scaled_dot_product_attention報(bào)錯(cuò)RuntimeError: cuDNN error: CUDNN_STATUS_NOT_SUPPORTED根源在于cuDNN 8.9.7編譯時(shí)鏈接的libcudnn.so.8版本號(hào)是GLIBC_2.27而Ubuntu 22.04的/lib/x86_64-linux-gnu/libc.so.6是GLIBC_2.35版本不兼容。解決方案只有兩個(gè)降級(jí)cuDNN用cuDNN 8.9.5兼容GLIBC_2.35升級(jí)OS用Ubuntu 24.04自帶GLIBC_2.39向下兼容我們選了方案2因?yàn)閏uDNN 8.9.5缺少對(duì)FlashAttention-2的FP16 kernel支持。這個(gè)決策背后是權(quán)衡ABI兼容性永遠(yuǎn)優(yōu)先于功能新特性。寧可不用新kernel也不能讓服務(wù)啟動(dòng)失敗。3.4 PyTorch與CUDA的ABI綁定為什么torch.version.cuda有時(shí)顯示錯(cuò)誤運(yùn)行python -c import torch; print(torch.version.cuda)輸出可能是11.8但實(shí)際PyTorch binary鏈接的是CUDA 12.1。這是因?yàn)镻yTorch的torch.version.cuda是從build時(shí)的環(huán)境變量CUDA_VERSION硬編碼進(jìn)binary的不是運(yùn)行時(shí)檢測。真實(shí)檢測法import torch print(Build CUDA:, torch.version.cuda) print(Runtime CUDA:, torch.cuda.get_device_properties(0).major) # 顯卡compute capability # 更準(zhǔn)檢查libcudart.so版本 import ctypes cudart ctypes.CDLL(libcudart.so.12) print(libcudart version:, cudart.cudaRuntimeGetVersion.__doc__)我們線上監(jiān)控腳本就用這套組合拳一旦發(fā)現(xiàn)build CUDA和runtime CUDA mismatch超過1個(gè)主版本如build11.8, runtime12.1立即告警——這往往預(yù)示著cudaMemcpyAsync行為異?;騭tream ordering失效。4. FlashAttention核心機(jī)制不是“更快的attention”而是“重寫GPU內(nèi)存訪問契約”4.1 標(biāo)準(zhǔn)Attention的內(nèi)存墻為什么O(N2)復(fù)雜度在GPU上是災(zāi)難標(biāo)準(zhǔn)scaled dot-product attention的計(jì)算流程Q K^T → [B, H, N, N] # attention scores softmax → [B, H, N, N] # 歸一化 scores V → [B, H, N, D] # 輸出問題出在中間的[B, H, N, N]矩陣。當(dāng)N2048、B1、H32、dtypefloat16時(shí)這個(gè)矩陣占用1 * 32 * 2048 * 2048 * 2 bytes 256 MB而A100的L2 cache只有40MBHBM帶寬雖高2TB/s但訪問延遲是瓶頸。一次global memory load需要800 cycles而計(jì)算一個(gè)MACmultiply-accumulate只要1 cycle。這意味著GPU大部分時(shí)間在等內(nèi)存ALU利用率不足20%。FlashAttention的破局點(diǎn)不是算法優(yōu)化而是重構(gòu)數(shù)據(jù)流把O(N2)的中間矩陣拆成O(N)的小塊在shared memory里流水線計(jì)算讓計(jì)算密度FLOPs/byte提升10倍。4.2 分塊調(diào)度tilingshared memory不是緩存是計(jì)算舞臺(tái)的布景FlashAttention的kernel核心是flash_fwd_kernel其shared memory布局像一個(gè)劇場--------------------- | Q_block (128x64) | ← 當(dāng)前Q塊128 seq, 64 head_dim --------------------- | K_block (128x64) | ← 對(duì)應(yīng)K塊與Q_block計(jì)算score --------------------- | V_block (128x64) | ← 對(duì)應(yīng)V塊用于加權(quán)求和 --------------------- | O_block (128x64) | ← 輸出塊累加結(jié)果 --------------------- | lse_block (128) | ← log-sum-exp臨時(shí)值用于softmax數(shù)值穩(wěn)定 ---------------------關(guān)鍵參數(shù)BLOCK_M128,BLOCK_N128不是隨便定的。它要滿足BLOCK_M * head_dim * 2 shared memory sizeA100是164KBBLOCK_N必須整除head_dim避免bank conflictBLOCK_M和BLOCK_N的乘積要接近GPU warp size32的整數(shù)倍保證warp內(nèi)load/store對(duì)齊我們實(shí)測過當(dāng)BLOCK_M64時(shí)shared memory利用率僅60%大量空閑當(dāng)BLOCK_M256時(shí)shared memory溢出觸發(fā)spill to local memory性能暴跌40%。128是A100上的黃金分割點(diǎn)。4.3 數(shù)值穩(wěn)定性設(shè)計(jì)log-sum-exp不是數(shù)學(xué)技巧是GPU浮點(diǎn)精度的妥協(xié)softmax的數(shù)值不穩(wěn)定眾所周知但FlashAttention的lselog-sum-exp實(shí)現(xiàn)有更深的考量// standard softmax exp_scores exp(scores - max_score); softmax_scores exp_scores / sum(exp_scores); // FlashAttention的lse float lse max_score log(sum(exp(scores - max_score))); // then use lse to normalize問題在于log(sum(exp(x)))在GPU上計(jì)算時(shí)exp(x)可能overflowx88.7 for float32。FlashAttention用warp-level reduction double precision intermediate解決double lse_warp 0.0; #pragma unroll for (int i 0; i 32; i) { if (i 32 valid[i]) { double exp_val exp((double)(scores[i] - max_val)); lse_warp exp_val; } } lse_block max_val log(lse_warp); // double precision log這里用double不是為了精度而是避免exp overflow。float32的exp最大輸入是88.7而double是709.8。在attention score中scores[i] - max_val范圍是[-10, 0]用float32足夠但為了保險(xiǎn)FlashAttention統(tǒng)一用double intermediate——這是用2倍寄存器消耗換100%數(shù)值安全。4.4 FlashAttention-2的kernel fusion把三次global memory訪問壓成一次FlashAttention-1的kernel分三階段Load Q_block, K_block → compute scores → store to shared memoryLoad scores, V_block → compute output → store to global memoryLoad O_block → reduce across blocks → final outputFlashAttention-2把這三階段fusion成一個(gè)kernel核心創(chuàng)新是persistent thread block一個(gè)block不再只處理一個(gè)Q_block而是循環(huán)處理多個(gè)Q_block復(fù)用已加載的K/V數(shù)據(jù)。偽代碼for (int start_m 0; start_m M; start_m BLOCK_M) { // load Q[start_m:start_mBLOCK_M, :] // load K, V (reused across Q blocks) for (int start_n 0; start_n N; start_n BLOCK_N) { // compute Q_block K_block^T → scores // scores V_block → O_block // accumulate to O_global } }效果是K/V數(shù)據(jù)只需從global memory load一次就能服務(wù)多個(gè)Q_block。實(shí)測在seq4096時(shí)global memory traffic減少62%kernel launch overhead降低35%因?yàn)閎lock數(shù)減少。我們線上服務(wù)把FlashAttention-1升級(jí)到-2后7B模型的prefill latency從128ms降到79ms提升38%。這不是算法勝利是GPU內(nèi)存帶寬利用率的勝利。5. 面試題實(shí)戰(zhàn)拆解從題目到生產(chǎn)環(huán)境的完整映射鏈5.1 第7題“請(qǐng)手寫一個(gè)支持fp16的warp shuffle reduce_max并說明__shfl_sync的mask參數(shù)含義”這題表面考API實(shí)則考三個(gè)層次語法層__shfl_sync的mask必須是warp size的bitmask0xFFFFFFFF for 32-lane語義層mask控制哪些lane參與shuffle不是“有效lane數(shù)”而是“參與shuffle的lane集合”硬件層mask為0的lane其val值在shuffle后保持不變但其他lane仍會(huì)從mask1的lane取值正確實(shí)現(xiàn)__device__ __forceinline__ float warp_reduce_max_fp16(half val) { float fval __half2float(val); for (int offset 16; offset 0; offset / 2) { float temp __shfl_sync(0xFFFFFFFF, fval, offset); fval fmaxf(fval, temp); } return fval; }陷阱在于__shfl_sync返回的是shuffle后的值不是原值。如果mask寫錯(cuò)如0xFFFFlane16~31的val會(huì)被忽略但lane0~15仍會(huì)從lane0~15取值導(dǎo)致max結(jié)果錯(cuò)誤。我們線上有個(gè)bug某次升級(jí)CUDA toolkit后__shfl_sync的mask默認(rèn)行為變了導(dǎo)致attention softmax的max值計(jì)算偏小最終輸出nan。定位過程花了6小時(shí)——這就是為什么面試要你手寫而不是背答案。5.2 第14題“FlashAttention中BLOCK_M和BLOCK_N如何選擇請(qǐng)給出A100上的具體數(shù)值及依據(jù)”標(biāo)準(zhǔn)答案是BLOCK_M128, BLOCK_N128但滿分回答必須包含shared memory constraintA100 shared memory per SM 164KB128*64*2*4 65536 bytesQ/K/V/O各128x64 fp16留足空間給lse和臨時(shí)變量bank conflict avoidanceBLOCK_N128head_dim64shared memory stride 128*2256 bytesbank index 256 % 32 0完美對(duì)齊每個(gè)bank只服務(wù)1個(gè)laneoccupancy trade-offBLOCK_M128時(shí)每個(gè)SM可駐留2個(gè)blockA100 SM count108total block216高于BLOCK_M256時(shí)的108個(gè)block但計(jì)算密度更高我們實(shí)測過BLOCK_M64時(shí)occupancy達(dá)100%但每個(gè)block計(jì)算量太小launch overhead占比35%BLOCK_M256時(shí)occupancy 50%但計(jì)算密度高整體吞吐反而低8%。128是平衡點(diǎn)。5.3 第22題“CUDA 12.8在WSL2中無法調(diào)用cudaMalloc錯(cuò)誤碼cudaErrorInvalidValue如何排查”這不是CUDA問題是WSL2的Windows driver ABI mismatch。排查鏈路nvidia-smi確認(rèn)Windows host driver version如535.104.05查NVIDIA官網(wǎng)compatibility table確認(rèn)該driver支持的最高CUDA版本535.104.05 → CUDA 12.2ls -l /usr/local/cuda確認(rèn)WSL2里裝的是CUDA 12.8超限卸載CUDA 12.8安裝CUDA 12.2ldd /usr/local/cuda-12.2/lib64/libcudart.so.12確認(rèn)依賴的glibc版本與WSL2匹配我們遇到過更隱蔽的情況Windows host driver是535.104.05但WSL2里裝了CUDA 12.2cudaMalloc仍失敗。原因是Windows update自動(dòng)升級(jí)了driver到536.67而WSL2未重啟——必須wsl --shutdown再重啟讓W(xué)SL2重新加載新driver。5.4 第25題“如果讓你設(shè)計(jì)一個(gè)AI Infra團(tuán)隊(duì)的CUDA能力評(píng)估體系你會(huì)怎么設(shè)計(jì)”我的答案是三級(jí)漏斗Level 1準(zhǔn)入能獨(dú)立完成CUDA環(huán)境搭建WSL2/裸機(jī)、編譯調(diào)試簡單kernel、讀懂Nsight Compute profiler報(bào)告識(shí)別memory bound vs. compute boundLevel 2交付能基于現(xiàn)有kernel做定制優(yōu)化如修改FlashAttention的BLOCK_SIZE適配特定顯卡、定位典型性能瓶頸bank conflict, warp divergence, memory coalescingLevel 3架構(gòu)能設(shè)計(jì)新kernel滿足業(yè)務(wù)需求如為稀疏attention設(shè)計(jì)專用kernel、主導(dǎo)CUDA版本升級(jí)遷移、建立團(tuán)隊(duì)CUDA code review checklist評(píng)估方式不是筆試而是真實(shí)任務(wù)給候選人一個(gè)線上慢query的Nsight trace讓他在2小時(shí)內(nèi)定位瓶頸并提交PR。我們?cè)眠@個(gè)方法篩掉90%的“理論高手”留下的人入職后3天就能介入核心優(yōu)化。最后分享個(gè)小技巧面試前把你本地的~/.bashrc里CUDA相關(guān)export全注釋掉用module load cuda/12.1代替。因?yàn)檎嬲腁I Infra工程師管理的是集群環(huán)境不是個(gè)人筆記本。