大神炮轟CUDA:CUDA存致命缺陷,它不是未來!這種新語言將打破英偉達(dá)的GPU壟斷地位,護(hù)城河終會(huì)消失! 原創(chuàng)
編輯 | 云昭
出品 | 51CTO技術(shù)棧(微信號(hào):blog51cto)
CUDA一直被視為英偉達(dá)GPU的最強(qiáng)壁壘,讓許多業(yè)界的玩家望洋興嘆。
但,今天這篇文章會(huì)給各位習(xí)慣C++、CUDA開發(fā)的大佬提個(gè)醒:
有一種新的編程語言,正在AI圈興起,撬動(dòng)英偉達(dá)的圍墻花園。而CUDA也不再是護(hù)城河。
近日,一位大牛 Thomas Cherickal,發(fā)表了一篇博客,闡述了一種新的編程范式。他認(rèn)為,基于 MLIR 的 Mojo 無疑將取代基于 LLVM 的 CUDA,而且這種方式已經(jīng)幾乎可以在其他任何芯片上運(yùn)行,包括谷歌TPU、AMD、英特爾以及任何定制的AI芯片!作者思路非常清晰,從市場(chǎng)競(jìng)爭(zhēng)格局、硬件和軟件的趨勢(shì)變化兩個(gè)角度,拆解了 CUDA 的優(yōu)勢(shì)和致命缺陷,并做出了論斷:CUDA 將走向終點(diǎn),而 Mojo 才是未來。篇幅較長(zhǎng),建議大家收藏細(xì)讀。
1.CUDA:一座看得見的圍墻花園
其實(shí),即便 OpenAI、DeepMind 這些 AI 巨頭,其實(shí)也都曾苦 CUDA 久矣。問題是,目前還沒什么好替代品。
自 2007 年推出以來,CUDA 一直是 GPU 編程的黃金標(biāo)準(zhǔn)。它讓開發(fā)者能夠更精細(xì)地控制 GPU,但也讓英偉達(dá)在軟硬一體的算力生態(tài)中建立了堅(jiān)固的護(hù)城河:
- 硬件綁定:只能運(yùn)行在英偉達(dá) GPU 上,AMD 或其他芯片基本無緣;
- 學(xué)習(xí)門檻高:使用 C++ 風(fēng)格,語法復(fù)雜,不適合初學(xué)者;
- 創(chuàng)新被封鎖:一旦你選了 CUDA,就意味著難以遷移,成本高、空間小。
從訓(xùn)練模型到部署推理,CUDA 的封閉性和高門檻,讓無數(shù)開發(fā)者又愛又恨。一邊是性能無敵的 GPU,一邊是寫起來像黑魔法一樣的 CUDA。
過去,AI 公司要想跑得快,幾乎只能選英偉達(dá)。
然而,Mojo 出現(xiàn)了,它帶來了一種更優(yōu)的方案。
2.英偉達(dá)的挑戰(zhàn)者越來越多,需要新的編程理念
在分析 Mojo 優(yōu)勢(shì)之前,不妨先研究下,英偉達(dá)硬件的競(jìng)爭(zhēng)者們。
到了2025年年中,情況在發(fā)生變化。IT界正在向異構(gòu)化徹底轉(zhuǎn)變。由此,我們看到科技巨頭從沒有放棄推出自己的芯片。
我們看到專用硬件遍地開花:
?英特爾Gaudi系列:
英特爾的Gaudi處理器專為深度學(xué)習(xí)訓(xùn)練和推理而設(shè)計(jì),是英偉達(dá)GPU的有力競(jìng)爭(zhēng)者。
?AMD Instinct MI系列:
AMD的MI系列GPU為高性能計(jì)算和AI工作負(fù)載而設(shè)計(jì),是英偉達(dá)數(shù)據(jù)中心GPU的競(jìng)爭(zhēng)者。
?Groq 張量流處理器(TSP):
Groq的TSP架構(gòu)為低延遲推理和高吞吐量而設(shè)計(jì),尤其適用于大語言模型。
?谷歌TPU:
谷歌的TPU是針對(duì)機(jī)器學(xué)習(xí)工作負(fù)載(尤其在谷歌云基礎(chǔ)架構(gòu)中)優(yōu)化的定制芯片。
?AWS Trainium:
AWS Trainium 是一款為機(jī)器學(xué)習(xí)訓(xùn)練而設(shè)計(jì)的芯片,具有高性能和成本效益。
除此之外,主攻定制芯片的初創(chuàng)公司也不在少數(shù)。而這種百花齊放的新格局需要一種新的編程理念。
3.拆解 CUDA:它究竟強(qiáng)大在哪里
CUDA 的全稱是統(tǒng)一計(jì)算設(shè)備架構(gòu)。它是英偉達(dá)的并行計(jì)算平臺(tái)和編程模型,允許開發(fā)者編寫類似 C++ 的代碼(稱為內(nèi)核),可在英偉達(dá) GPU 上運(yùn)行。
CUDA的真正優(yōu)勢(shì)在于常年積累的庫生態(tài),其成熟度可以說市面上無與倫比。這里展示一些:
?數(shù)學(xué)庫:
cuBLAS:用于基本線性代數(shù)子程序(BLAS)。
cuRAND:用于隨機(jī)數(shù)生成。
cuFFT:用于快速傅里葉變換。
cuSPARSE:用于稀疏矩陣運(yùn)算。
cuTENSOR:用于張量運(yùn)算。
cuSOLVER:用于稠密和稀疏直接求解器。
?并行算法庫:
nvGRAPH:用于圖算法。
Thrust:用于并行算法和數(shù)據(jù)結(jié)構(gòu)。
?通信庫:
NVSHMEM:用于分區(qū)全局地址空間(PGAS)編程。
NCCL:用于多GPU和多節(jié)點(diǎn)集體通信。
?深度學(xué)習(xí)庫:
cuDNN:用于深度神經(jīng)網(wǎng)絡(luò)計(jì)算。
TensorRT:用于優(yōu)化深度學(xué)習(xí)推理。
Riva:用于對(duì)話式AI。
DALI:用于深度學(xué)習(xí)的數(shù)據(jù)加載和增強(qiáng)。
此外,CUDA 還對(duì)硬件實(shí)現(xiàn)了直接底層控制,使研究人員能夠獲得最佳性能;另外,悠久的歷史造就了龐大的社區(qū),擁有豐富的文檔和支持。
4.但,CUDA也有致命缺陷
Cherickal 認(rèn)為,CUDA 的致命缺陷就在于它的“牢籠”。
廠商鎖定:CUDA代碼只能在英偉達(dá)GPU上運(yùn)行。這導(dǎo)致開發(fā)者和整個(gè)行業(yè)被一家收費(fèi)高昂的硬件供應(yīng)商牢牢束縛。這抑制了競(jìng)爭(zhēng),并限制了選擇最佳硬件的自由。
雙語言問題:AI和科學(xué)計(jì)算的主要瓶頸。研究人員使用Python等高級(jí)語言設(shè)計(jì)原型,因?yàn)楹?jiǎn)單易用、迭代速度快。但對(duì)于生產(chǎn)環(huán)境而言,關(guān)注性能的代碼必須完全用低級(jí)C++/CUDA重寫。這造成了痛苦且昂貴的脫節(jié),減緩了從研究到部署的進(jìn)程。
編程復(fù)雜性:CUDA功能強(qiáng)大,但異常復(fù)雜和冗繁。開發(fā)者被迫手動(dòng)管理內(nèi)存,在CPU(主機(jī))和GPU(設(shè)備)之間傳輸數(shù)據(jù)。開發(fā)者還必須成為硬件調(diào)度員,管理線程塊、網(wǎng)格和同步。這種復(fù)雜性導(dǎo)致學(xué)習(xí)曲線陡峭,常常導(dǎo)致難以察覺的bug。
5.編譯器技術(shù):LLVM 面臨的問題
再來看編譯器方面。大家首先會(huì)想到的是 LLVM。
LLVM項(xiàng)目是一系列模塊化且可重用的編譯器技術(shù)。其核心是 LLVM 中間表示(IR),這是一種類似匯編的低級(jí)語言。LLVM 已成為現(xiàn)代編譯器后端的標(biāo)準(zhǔn),尤其適用于 CPU。編譯器前端(比如面向C++的Clang)將源代碼轉(zhuǎn)換成LLVM IR。然后,LLVM 后端優(yōu)化該 IR,將其轉(zhuǎn)換成特定 CPU 的機(jī)器碼。這種模塊化在當(dāng)時(shí)是革命性的。
然而,LLVM 是為以 CPU 為中心的時(shí)代設(shè)計(jì)的。對(duì)于異構(gòu)硬件盛行的新時(shí)代來說,其 IR 過于低級(jí)。
它會(huì)丟失源代碼中重要的高級(jí)信息,這個(gè)問題名為“語義鴻溝”(semantic gap)。比如說,在編譯 TensorFlow 模型時(shí),某個(gè)運(yùn)算是卷積運(yùn)算的知識(shí)或信息會(huì)丟失。
LLVM IR 只能識(shí)別一組寬泛的循環(huán)和算術(shù)指令。這使得編譯器無法執(zhí)行強(qiáng)大的、針對(duì)特定領(lǐng)域的優(yōu)化。它不再理解程序員的高級(jí)意圖。這就是“語義鴻溝問題”的本質(zhì),而MLIR解決了這個(gè)問題。
這里科普一下:
CUDA 的編譯流程部分借助了 LLVM IR(NVVM),但整體還是閉源且偏向傳統(tǒng)的硬編碼式工具鏈;而 Mojo 則選擇原生擁抱 MLIR(一個(gè)更現(xiàn)代、更模塊化的 LLVM 子項(xiàng)目),在可擴(kuò)展性與多架構(gòu)適配性上更進(jìn)一步。
6.MLIR:最后一塊拼圖
MLIR(Multi-Level Intermediate Representation,多級(jí)中間表示)誕生于谷歌,最初是為了解決 TensorFlow 無法統(tǒng)一編譯到 CPU、GPU 和自家 TPU 的問題。
他們很快發(fā)現(xiàn):LLVM 傳統(tǒng)的單一、底層中間表示(IR)已經(jīng)無法勝任現(xiàn)代異構(gòu)硬件的復(fù)雜需求。
MLIR 的突破點(diǎn)在于,它提供了一個(gè)統(tǒng)一的基礎(chǔ)架構(gòu),可以定義、組合多個(gè)不同層次的 IR。
這些可組合的 IR 被稱為 “方言(dialects)”。
你可以把 MLIR 理解為一個(gè)“硬件通用翻譯器”,它能同時(shí)理解從高級(jí)語言語義到底層硬件細(xì)節(jié)的所有層級(jí)。每種方言都代表了一個(gè)特定領(lǐng)域或抽象層級(jí):
- 比如,“TensorFlow 方言”中就直接包含了 tf.conv2d 這樣的卷積操作;
- 而“線性代數(shù)方言”則定義了 linalg.matmul 這樣的矩陣乘法。
這使得 高級(jí)語義得以完整保留,而不是像傳統(tǒng)編譯器那樣一上來就扁平化處理。
這樣做的最大好處,就是能啟用一種更強(qiáng)大的編譯策略:逐步降階(progressive lowering)。
編譯器不再一口氣把高級(jí)代碼壓成底層匯編,而是像“剝洋蔥”一樣,一層層轉(zhuǎn)化:
- 從高級(jí)方言(如 TensorFlow)開始,執(zhí)行特定領(lǐng)域的優(yōu)化;
- 然后逐步“降階”,轉(zhuǎn)換為更低層次的中間方言(如線性代數(shù)方言、內(nèi)存訪問方言等);
- 每個(gè)中間階段都有獨(dú)立的優(yōu)化策略;
- 最后才進(jìn)入底層方言,如 LLVM IR,用于生成最終機(jī)器碼。
這種方式能 盡可能長(zhǎng)時(shí)間地保留高階語義上下文,從而帶來更精準(zhǔn)、更有針對(duì)性的編譯優(yōu)化。
因此,在高級(jí)語言和多樣化芯片架構(gòu)之間,MLIR 是目前最有希望的橋梁。
它不僅解決了 “一語言綁一硬件” 的問題,還讓開發(fā)者和編譯器都可以更自由地定義優(yōu)化路徑。
簡(jiǎn)言之:
MLIR 是連接高級(jí)編程與底層芯片世界的“關(guān)鍵接口層”。
無論你是寫 AI 框架、區(qū)塊鏈虛擬機(jī),還是芯片設(shè)計(jì)工具,MLIR 都是值得關(guān)注的底層基石。
7.最前沿的語言,為什么是 Mojo?
如果說 MLIR 是強(qiáng)大又復(fù)雜的引擎,Mojo 就是簡(jiǎn)潔直觀的用戶界面。
2023 年 5 月,Mojo 由 LLVM 和 Swift 語言的原始架構(gòu)師 Chris Lattner 創(chuàng)建。其設(shè)計(jì)理念遵循第一原則,旨在成為 MLIR 時(shí)代的完美語言,是一種可在多個(gè)平臺(tái)上實(shí)現(xiàn)快速且可移植的 CPU+GPU 代碼的編程語言。
就這一點(diǎn)而言,可以說,Mojo 是當(dāng)今技術(shù)最先進(jìn)的語言。
因?yàn)椋幢闶墙鼛啄甏鬅岬?nbsp;Rust,也都是基于 LLVM 的,所以具有 LLVM 的所有缺點(diǎn)。而 Mojo 則是當(dāng)今唯一基于 MLIR 的主流編程語言。
Mojo 的主要功能有以下幾個(gè):
(1)Python 的超集
?Mojo 旨在與現(xiàn)有的Python生態(tài)系統(tǒng)完全兼容,這是一項(xiàng)殺手級(jí)功能!
?它允許開發(fā)者導(dǎo)入和使用任何Python庫,比如NumPy、Pandas或Matplotlib。
?它通過利用Python龐大的生態(tài)系統(tǒng),完全規(guī)避了新語言面臨的“冷啟動(dòng)”問題。
(2)真正的系統(tǒng)編程特性:
?與Python不同,Mojo是一種具有強(qiáng)靜態(tài)類型的編譯語言。
?這消除了一大批的運(yùn)行時(shí)錯(cuò)誤,并實(shí)現(xiàn)了C++級(jí)的性能優(yōu)化。
?它引入了現(xiàn)代內(nèi)存管理概念以確保內(nèi)存安全,比如所有權(quán)和借用(源自Rust),沒有垃圾收集器的開銷。
(3)一流的MLIR集成:
?Mojo將MLIR的全部功能直接展現(xiàn)給開發(fā)者。
?程序員可以為應(yīng)用程序的大部分編寫類似Python的高級(jí)代碼。
?需要最高性能時(shí),可以降級(jí)使用特定的MLIR方言,并編寫低級(jí)內(nèi)核。
?重要的是,這一切可以在同一個(gè)文件中使用同一種語言完成。
此外,Mojo 還輕松解決了“雙語言問題”。
8.代碼PK:Mojo如何秒殺CUDA
理論是一回事,實(shí)踐是另一回事。以下完整且實(shí)用的代碼示例,將展示兩種范式之間的重大差異。
篇幅原因,這里只舉一個(gè)“矩陣乘法”的示例。
完整的CUDA實(shí)現(xiàn)
這是一個(gè)完整的、可編譯的CUDA矩陣乘法程序。
// Filename: matmul.cu
// To compile: nvcc matmul.cu -o matmul_cuda
#include <iostream>
#include <vector>
#include <cuda_runtime.h>
// Helper to check for CUDA errors
#define CUDA_CHECK(err) { \
cudaError_t err_code = err; \
if (err_code != cudaSuccess) { \
std::cerr << "CUDA Error: " << cudaGetErrorString(err_code) << " at line " << __LINE__ << std::endl; \
exit(EXIT_FAILURE); \
} \
}
// CUDA Kernel for Matrix Multiplication (Device Code)
__global__ void matrixMulKernel(float* C, const float* A, const float* B, int N) {
// Calculate the global row and column index of the element
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
// Boundary check to avoid accessing out-of-bounds memory
if (row < N && col < N) {
float p_value = 0.0f;
// Each thread computes one element of the result matrix C
for (int k = 0; k < N; ++k) {
p_value += A[row * N + k] * B[k * N + col];
}
C[row * N + col] = p_value;
}
}
// Main function (Host Code)
int main() {
constint N = 256;
constint size = N * N * sizeof(float);
// Step 1. Allocate host memory
std::vector<float> h_A(N * N);
std::vector<float> h_B(N * N);
std::vector<float> h_C(N * N);
// Initialize host matrices
for (int i = 0; i < N * N; ++i) {
h_A[i] = static_cast<float>(rand()) / RAND_MAX;
h_B[i] = static_cast<float>(rand()) / RAND_MAX;
}
// Step 2. Allocate device memory
float *d_A, *d_B, *d_C;
CUDA_CHECK(cudaMalloc((void**)&d_A, size));
CUDA_CHECK(cudaMalloc((void**)&d_B, size));
CUDA_CHECK(cudaMalloc((void**)&d_C, size));
// Step 3. Copy matrices from host to device
std::cout << "Copying data from host to device..." << std::endl;
CUDA_CHECK(cudaMemcpy(d_A, h_A.data(), size, cudaMemcpyHostToDevice));
CUDA_CHECK(cudaMemcpy(d_B, h_B.data(), size, cudaMemcpyHostToDevice));
// Step 4. Define kernel launch configuration
// Use 16x16 threads per block, a common choice
dim3 threadsPerBlock(16, 16);
// Calculate the number of blocks needed in each dimension
dim3 numBlocks((N + threadsPerBlock.x - 1) / threadsPerBlock.x, (N + threadsPerBlock.y - 1) / threadsPerBlock.y);
// Step 5. Launch the kernel on the device
std::cout << "Launching kernel..." << std::endl;
matrixMulKernel<<<numBlocks, threadsPerBlock>>>(d_C, d_A, d_B, N);
CUDA_CHECK(cudaGetLastError());
CUDA_CHECK(cudaDeviceSynchronize()); // Wait for the kernel to finish
// Step 6. Copy the result matrix back from device to host
std::cout << "Copying result from device to host..." << std::endl;
CUDA_CHECK(cudaMemcpy(h_C.data(), d_C, size, cudaMemcpyDeviceToHost));
// Step 7. Free device memory
CUDA_CHECK(cudaFree(d_A));
CUDA_CHECK(cudaFree(d_B));
CUDA_CHECK(cudaFree(d_C));
std::cout << "CUDA Matrix Multiplication finished successfully." << std::endl;
// (Optional: Add verification step here)
return0;
}CUDA代碼分析:
代碼主要由樣板代碼和低級(jí)管理組成。步驟1、2、3、6和7 純粹用于跨CPU/GPU邊界管理內(nèi)存。這很繁瑣,容易出錯(cuò),并掩蓋核心算法。全局關(guān)鍵字、blockIdx、threadIdx和<<<...>>>語法是CUDA特有的硬件抽象。
該代碼根本上永久地與英偉達(dá)的硬件架構(gòu)緊密相關(guān)。實(shí)際算法:三個(gè)嵌套循環(huán)只占總代碼的一小部分。程序員的精力耗費(fèi)在了硬件管理上,而不是問題本身上。
完整的Mojo實(shí)現(xiàn)
Mojo 版本以驚人的簡(jiǎn)潔性和強(qiáng)大功能實(shí)現(xiàn)了相同的效果。
# Filename: matmul.mojo
# To run: mojo matmul.mojo
from memory import DType, Tensor
from random import rand
from time import now
fn matmul_naive(C: Tensor[DType.float32], A: Tensor[DType.float32], B: Tensor[DType.float32]):
"""A naive, high-level implementation of matrix multiplication."""
let N = A.dim(0)
let M = A.dim(1)
let P = B.dim(1)
for i in range(N):
for j in range(P):
var sum: Float32 = 0.0
for k in range(M):
sum += A.load(i, k) * B.load(k, j)
C.store(i, j, sum)
fn main():
let N = 256
# 1. Allocate and initialize tensors.
# Mojo's Tensor handles memory allocation automatically.
# The compiler will place it in the most appropriate memory space.
var A = Tensor[DType.float32](N, N)
var B = Tensor[DType.float32](N, N)
var C = Tensor[DType.float32](N, N)
for i in range(N):
for j in range(N):
A.store(i, j, rand[DType.float32]())
B.store(i, j, rand[DType.float32]())
print("Starting Mojo Matrix Multiplication...")
let start_time = now()
# 2. Call the function.
# The MLIR-based compiler optimizes this high-level code.
# It can automatically tile, vectorize, and parallelize this code
# for the target hardware (CPU, GPU, etc.).
matmul_naive(C, A, B)
let end_time = now()
let duration_ms = (end_time - start_time) / 1_000_000.0
print("Mojo Matrix Multiplication finished successfully.")
print("Execution time:", duration_ms, "ms")
# (Optional: Print a corner of the result matrix to verify)
print("Result C[0,0]:", C.load(0,0))
}就是這樣!Mojo方法出色得多。
首先是,可編程性和專注性:
?Mojo代碼簡(jiǎn)潔明了,直接表達(dá)算法。
?程序員專注于“什么”(數(shù)學(xué)運(yùn)算),而不是“如何”(內(nèi)存?zhèn)鬏敚?/p>
?無需手動(dòng)執(zhí)行cudaMalloc、cudaMemcpy 或 cudaFree。
?這類錯(cuò)誤全部消失。
其次,它注重性能的抽象:
?執(zhí)行的不是簡(jiǎn)單的嵌套循環(huán)。
?基于MLIR的編譯器可以執(zhí)行復(fù)雜的轉(zhuǎn)換。
?這將這段簡(jiǎn)單代碼轉(zhuǎn)換成高度優(yōu)化的內(nèi)核。
?它可以自動(dòng)運(yùn)用平鋪、矢量化和并行化。
?程序員可以添加提示(比如@vectorize或@parallelize)以指導(dǎo)編譯器,實(shí)現(xiàn)控制,而無需增加復(fù)雜性。
最重要的是,終極優(yōu)勢(shì):可移植性。這是關(guān)鍵點(diǎn)。
?同一個(gè)matmul.mojo文件可以重新編譯,以便在英偉達(dá)GPU、AMD GPU、搭載AVX512 的英特爾CPU或谷歌TPU上運(yùn)行。
?邏輯保持不變;編譯器后端發(fā)生變化。
?CUDA 代碼需要針對(duì)每個(gè)新的硬件目標(biāo)進(jìn)行全面且昂貴的重寫。
?Mojo 提供“性能可移植性”,打破了廠商鎖定,使代碼適應(yīng)未來需要。
所以長(zhǎng)期看,基于 MLIR 的 Mojo 無疑將取代基于 LLVM 的 CUDA(部分基于),開發(fā)者將享受這一變化!
9.Mojo重新定義了游戲規(guī)則
為什么這么說?
(1)職責(zé)分離,思維方式的顛覆
Mojo 與 CUDA 的最大區(qū)別,在于它們對(duì)“程序員該關(guān)心什么”的定義截然不同:
- Mojo 代碼:專注于算法本身開發(fā)者只需表達(dá)“我要做什么”,即模型的計(jì)算邏輯和結(jié)構(gòu);
- CUDA 代碼:專注于硬件實(shí)現(xiàn)開發(fā)者需要手動(dòng)指定線程分布、內(nèi)存布局等 GPU 底層細(xì)節(jié)。
這種區(qū)別不是小修小補(bǔ),而是編程范式的根本轉(zhuǎn)變。在 Mojo 中,開發(fā)者可以把精力放在如何改進(jìn)算法上;而具體“怎么映射到芯片上”,交給 MLIR 編譯器自動(dòng)完成。
(2)更快的研究周期、更低的心智負(fù)擔(dān)
在 AI 研究中,嘗試一個(gè)新模型結(jié)構(gòu)或優(yōu)化一個(gè)訓(xùn)練技巧,是日常操作。
- 用 Mojo 寫的模型邏輯清晰、可讀性強(qiáng),研究人員可以輕松修改并快速驗(yàn)證想法;
- 相比之下,CUDA 的底層代碼常常需要大量位運(yùn)算、手動(dòng)調(diào)度線程、控制內(nèi)存訪問——?jiǎng)右幌露枷癫鹨嫔w改引擎,又慢又容易出錯(cuò)。
這意味著:Mojo 能大幅加速 AI 的研發(fā)周期,真正做到“想法立刻變成實(shí)驗(yàn)”。
(3)最關(guān)鍵的:硬件自由
Mojo 寫出來的代碼不是專屬于 NVIDIA 的!通過 MLIR 的多級(jí)中間表示,Mojo 代碼可以編譯運(yùn)行在多種硬件上:
- AMD GPU
- Google TPU
- Intel Gaudi
- 各類定制 AI 加速芯片(如 AI Startup 的專用 ASIC)
甚至只要定義新的“方言”,未來任何新架構(gòu)都能支持。
這意味著:
Mojo 代碼是“面向未來”的,不被任何一家芯片廠商鎖死。
這也是打破英偉達(dá)壟斷、推動(dòng)算力成本下降的關(guān)鍵一環(huán)。
10.最終:CUDA的終點(diǎn),Mojo的未來
當(dāng)我們將目光從當(dāng)下主流的密集矩陣運(yùn)算,轉(zhuǎn)向未來更廣闊的計(jì)算領(lǐng)域時(shí),CUDA 的局限就開始暴露。而 MLIR + Mojo 的組合,正是為這種異構(gòu)、多樣、并發(fā)、稀疏甚至非傳統(tǒng)的計(jì)算范式而生。
作者舉了一個(gè)算力進(jìn)化的例子:區(qū)塊鏈。
比特幣這類工作量證明(PoW)機(jī)制的區(qū)塊鏈,需要巨大的哈希運(yùn)算能力。
目標(biāo)是找到一個(gè)“nonce”(隨機(jī)數(shù)),使其與區(qū)塊數(shù)據(jù)一起哈希后的結(jié)果小于目標(biāo)值——這完全是暴力窮舉搜索,最適合并行加速硬件。
- 起初人們用 CPU;
- 后來轉(zhuǎn)向并行能力更強(qiáng)的 GPU;
- 再后來,進(jìn)入 ASIC(專用集成電路) 時(shí)代。
比如:SHA-256 的 ASIC,把哈希算法直接寫入了硅片,能效比 GPU 高出幾個(gè)數(shù)量級(jí)。
這就是 CUDA 的終點(diǎn)。但 Mojo 和 MLIR 的故事才剛開始。
MLIR + Mojo 如何改變芯片設(shè)計(jì)呢?
芯片設(shè)計(jì)領(lǐng)域有個(gè)術(shù)語叫 HLS(高階綜合):把高級(jí)算法描述轉(zhuǎn)成硬件電路語言(如 Verilog 或 VHDL)并燒錄進(jìn)芯片。
MLIR,借助項(xiàng)目如 CIRCT(專為硬件設(shè)計(jì)的 MLIR 子項(xiàng)目),正是下一代 HLS 的核心支撐。
一段 Mojo 寫的哈希算法代碼,可以編譯為:
- GPU 上運(yùn)行的并行程序(通過 GPU 后端);
- 或直接轉(zhuǎn)為 Verilog,用于設(shè)計(jì)專屬 ASIC 芯片。
同一段 Mojo 代碼,同時(shí)通往軟件和硬件的兩個(gè)世界。
這就是 MLIR 帶來的“從軟件到硅”的編譯能力 —— CUDA 無法涉足的疆域。
寫在最后:Mojo會(huì)是贏家嗎
一方面,未來是異構(gòu)芯片的天下,這并非猜測(cè),而是事實(shí)。廠商鎖定所帶來的商業(yè)和技術(shù)風(fēng)險(xiǎn)不可接受。
另一方面,隨著時(shí)間演進(jìn),如今 GPU 僵硬的 SIMT 模式不再適應(yīng)稀疏數(shù)據(jù)、神經(jīng)形態(tài)AI、區(qū)塊鏈和量子計(jì)算的發(fā)展趨勢(shì)。
而 MLIR 是目前唯一一種旨在解決這個(gè)問題且得到業(yè)界支持的架構(gòu)。
同時(shí),谷歌、蘋果、英特爾、AMD 和 ARM 紛紛采用,清晰地表明了其在未來編譯器領(lǐng)域的核心地位。
而, Mojo 恰恰是迄今唯一能夠駕馭這種強(qiáng)大功能的語言。
Mojo解決了雙語言問題,兼具易用性和性能,并提供了通往整個(gè) MLIR 生態(tài)系統(tǒng)的門戶。
因此,從 CUDA 到基于 MLIR 的世界的過渡將是漸進(jìn)的過程,卻又是不可避免的。這是從以硬件為中心的封閉模式向軟件定義的開放未來的根本性轉(zhuǎn)變。
但從長(zhǎng)遠(yuǎn)來看,Mojo 會(huì)是贏家嗎?Mojo 弱勢(shì)在于生態(tài)還沒有成熟。
但目前看,至少開發(fā)者會(huì)更喜歡 Mojo,而不是 CUDA。
這篇懟CUDA的文章終于結(jié)束了,老規(guī)矩,大佬們?cè)趺纯矗繗g迎評(píng)論區(qū)交流。
參考鏈接:
??https://hackernoon.com/this-new-language-might-kill-nvidias-gpu-monopoly??
??https://hackernoon.com/meet-mojo-the-language-that-could-replace-python-c-and-cuda?embedable=true??
本文轉(zhuǎn)載自??51CTO技術(shù)棧??,作者:云昭

















