Présentation
Vx se positionne comme un langage de programmation système dédié à l’informatique hétérogène. Il intègre les différents espaces mémoire – CPU, GPU, NPU et autres accélérateurs – directement dans son système de types. Ainsi, une tentative de déréférencer un pointeur de dispositif depuis le thread hôte est détectée à la compilation, évitant les segfaults nocturnes classiques.
Typage hétérogène et vérifications à la compilation
Le type Pinned<Tensor<f32,[4,4]>,Topology::NPU[0]> indique explicitement que le tenseur réside dans la mémoire haute bande passante du NPU. Le transfert entre espaces mémoire nécessite l’appel transfer(), même si le matériel partage une mémoire unifiée, ce qui rend la localisation des données vérifiable dans le code source. Le compilateur applique plusieurs règles : adresse‑space typing (interdiction de mélanger pointeurs hôte/accélérateur), capacité d’admission (vérification que la taille demandée tient dans la mémoire cible), contrats de séam (lecture d’un tampon avant que le transfert asynchrone ne soit visible), types linéaires (détection d’usage après déplacement), atteignabilité topologique (interdiction de transfert entre espaces non reliés) et autodiff (interdiction de différencier une région sans adjoint). Ces contrôles sont résolus par un prouveur SMT intégré.
fn custom_matmul(
a: Pinned<Tensor<f32,[4,4]>, Topology::NPU[0]>,
b: Pinned<Tensor<f32,[4,4]>, Topology::NPU[0]>
) -> Verified<Tensor<f32,[4,4], Memory::NPU_HBM>> {
let mut result = Tensor<f32,[4,4], Memory::NPU_HBM>::uninit();
spawn on (Topology::NPU[0]) {
for i in 0..4 {
for j in 0..4 {
result[i][j] = 0.0;
for k in 0..4 {
result[i][j] += a[i][k] * b[k][j];
}
}
}
}
return Verified(result);
}
Compilation et backends
Le frontend de Vx génère un identifiant plat de 256 bits pour chaque symbole, type nominal et variante monomorphisée. Cette représentation, couplée à un système de types nominal et à un boxing obligatoire pour les types récursifs, permet une compilation parallèle sans contention de verrous. Le flux de compilation produit du MLIR identique, que le processus soit mono‑thread ou multi‑thread, ce qui est vérifié par un test‑suite exhaustif. Le MLIR est ensuite consommé par les backends : CPU (x86‑64, arm64) via LLVM IR, GPU NVIDIA via NVVM → PTX → SASS, et Apple AMX/ANE via un plugin CoreML. Les fournisseurs peuvent étendre le compilateur en ajoutant des passes MLIR, évitant ainsi les patches du cœur.
Limites et cas d’usage
Vx excelle lorsqu’une application doit être à la fois correcte et performante sur une variété de silicium – par exemple les pipelines d’inférence où chaque transfert doit être certifié. En revanche, les charges de travail dynamiques typiques de PyTorch, où la forme du tenseur change à chaque itération, imposent des coûts de recompilation qui rendent Vx moins adapté. Le modèle de machine file, qui décrit la hiérarchie mémoire (ex. HBM 80 GiB, bande passante 3.35 TB/s, L2 50 MiB, etc.), garantit que les limites physiques sont respectées avant même la génération du binaire.