IntrodEntendiendo WASI Threads: Paralelismo eficiente en WebAssembly
Siguiendo nuestra serie de artículos sobre WebAssembly (Wasm), hoy hablaremos de como traer paralelismo a WebAssembly. Con el crecimiento del ecosistema WebAssembly, cada vez son más las aplicaciones que buscan beneficiarse de su portabilidad, seguridad y rendimiento. Sin embargo, una limitación importante hasta la fecha ha sido la falta de soporte para ejecución de código multihilo. Ahí es donde entra WASI Threads, una propuesta clave para llevar el paralelismo nativo al entorno Wasm de forma segura y eficiente.
En esta entrada exploraremos qué es WASI Threads, cómo funciona y por qué es un paso fundamental para el futuro de Wasm.ucción
Primero de todo, un recordatorio sobre WASI
WASI (WebAssembly System Interface) es una interfaz estándar que permite que los módulos Wasm interactúen con el sistema operativo (archivos, red, reloj, etc.) de forma segura y portable, sin acceso directo al hardware o a llamadas nativas como open() o fork(), que dependen del sistema operativo subyacente.
En el caso que nos ocupa, el modelo de ejecución de Wasm ha sido estrictamente monohilo, siguiendo el comportamiento en los navegadores, lo que limitaba su uso en tareas computacionalmente intensivas, como procesamiento de imágenes, bases de datos, simulaciones físicas o aprendizaje automático.
WASI Threads: El siguiente paso
WASI Threads es una extensión propuesta al estándar WASI que habilita el uso de hilos nativos en WebAssembly. Su objetivo es permitir que una aplicación Wasm aproveche múltiples núcleos del CPU, usando una API basada en pthreads (std::thread en C++/Rust), pero en un entorno controlado y seguro. Con WASI Threads es posible ejecutar de forma paralela el siguiente programa para sumar 1000 números:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 4
#define ARRAY_SIZE 1000
int array[ARRAY_SIZE];
long partial_sums[NUM_THREADS];
typedef struct {
int thread_id;
int start;
int end;
} thread_args_t;
void* compute_sum(void* arg) {
thread_args_t* args = (thread_args_t*)arg;
long sum = 0;
for (int i = args->start; i < args->end; ++i) {
sum += array[i];
}
partial_sums[args->thread_id] = sum;
return NULL;
}
int main() {
// Inicializa el array
for (int i = 0; i < ARRAY_SIZE; ++i) {
array[i] = 1; // Valor fijo para fácil verificación
}
pthread_t threads[NUM_THREADS];
thread_args_t args[NUM_THREADS];
int chunk_size = ARRAY_SIZE / NUM_THREADS;
// Crear hilos
for (int i = 0; i < NUM_THREADS; ++i) {
args[i].thread_id = i;
args[i].start = i * chunk_size;
args[i].end = (i == NUM_THREADS - 1) ? ARRAY_SIZE : (i + 1) * chunk_size;
pthread_create(&threads[i], NULL, compute_sum, &args[i]);
}
// Esperar a que los hilos terminen
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
// Sumar los resultados parciales
long total = 0;
for (int i = 0; i < NUM_THREADS; ++i) {
total += partial_sums[i];
}
printf("Suma total: %ld\n", total);
return 0;
}
¿Cómo funciona?
WASI Threads se basa en:
- Memoria compartida: Se habilita la memoria compartida entre instancias Wasm que se ejecutan de forma concurrente en distintos hilos en el espacio de usuario.
- Hilos en el entorno anfitrión: Cada hilo de Wasm es gestionado por el sistema operativo subyacente mediante hilos nativos. Típicamente, por cada hilo de Wasm, la máquina virtual crea un hilo nativo, manteniendo una correspondencia 1:1 entre hilos Wasm e hilos del sistema.
- Función status wasi_thread_spawn(thread_start_arg* start_arg): Esta función es llamada desde el módulo Wasm y sirve para solicitar a la máquina virtual la creación de un nuevo hilo de ejecución Wasm.
- Requisitos actuales: Esta funcionalidad requiere habilitar ciertas opciones experimentales tanto al compilar como al ejecutar, y solo está disponible en máquinas virtuales que ya soportan WASI Threads, como Wasmtime, Wasmer o WAMR. Por ejemplo, en Wasmtime esto requiere usar el flag –enable-threads:
$wasmtime run --enable-threads parallel.wasm
Retos de seguridad y aislamiento
Uno de los desafíos clave en la incorporación de hilos a Wasm es mantener el aislamiento entre módulos. El uso de memoria compartida introduce riesgos clásicos como condiciones de carrera (data races) o bloqueos mutuos (deadlocks). Por eso, WASI Threads incorpora mecanismos para garantizar:
- Control de acceso a memoria compartida, que se garantiza mediante el uso de instrucciones de acceso atómico como
i32.atomic.rmw.cmpxchg
. - Aislamiento entre instancias en sistemas multiusuario.
¿Por qué importa WASI Threads?
Con el soporte multihilo, Wasm se convierte en una opción viable para:
- Servidores edge multiusuario
- Procesamiento en paralelo (ML, multimedia)
- Portabilidad de librerías multihilo de C/C++/Rust
- Aplicaciones científicas y de alto rendimiento (HPC)
En un reciente artículo publicado en la prestigiosa conferencia IEEE CCGrid’25, titulado ‘Let It Unthread: The Good, The Bad and The Ugly within WebAssembly Portable Multithreading’, se demuestra que Wasmtime puede alcanzar un rendimiento cercano al nativo (glibc) en aplicaciones reales como blackscholes, fluidanimate o swaptions.

Conclusión
WASI Threads representa un hito en la evolución de WebAssembly: un paso decisivo hacia la ejecución eficiente y paralela en un entorno portable, seguro y moderno. Aunque aún está en fase experimental, su desarrollo avanza con rapidez, y todo indica que será una pieza clave del futuro de la computación basada en WebAssembly.
Leave a Reply