Ok, nesse caso, você está provavelmente se referindo a 2 coisas:
- Operações SIMD, via intrínsecos da arquitetura;
- Sintaxe vetorial, sem loops, em linguagens como Python;
Independente disso, todos os OSes modernos suportam o que é necessário para fazer uso de operações SIMD. Você vai apenas precisar se preocupar com a arquitetura e linguagem. No caso da arquitetura, vai precisar verificar se o processador vai oferecer suporte aos intrínsecos, e no caso da linguagem, vai precisar usar o algoritmo e/ou bibliotecas adequadas.
A forma mais rápida de fazer uso da programação vetorial vai ser via Python, por exemplo:
import numpy as np
a = np.random.rand(1000).astype(np.float32)
b = np.random.rand(1000).astype(np.float32)
c = a + b
s = np.sum(c) # redução vetorial
dot = a @ b # produto interno (BLAS por baixo)
# broadcasting:
X = np.random.rand(1000, 256).astype(np.float32)
w = np.random.rand(256).astype(np.float32)
y = w + 10
Z = X * y # w “expande” na dimensão certa
Por baixo dos panos, o Python + numpy (ou outra biblioteca para operações vetoriais com otimização) na maioria das vezes já faz uso das instruções SIMD adequadas. Existem outras bibliotecas, metodos via numba, etc…
Em C, o compilador às vezes detecta casos no seu código e otimiza sozinho, mas frequentemente, você precisa ser um pouco mais explicito, otimizando o espaço em memória deos ponteiros, e forçando a detecção com pragmas:
void add_float(size_t n,
const float * restrict a,
const float * restrict b,
float * restrict c)
{
#pragma omp simd // se quiser forçar
for (size_t i = 0; i < n; ++i) {
c[i] = a[i] + b[i];
}
}
Geralmente vai precisar massagear o compilador com algumas flags, por exemplo, para GCC/Clang: -O3 -march=native, dentre outras.
Ainda assim, não é garantia total em qualquer algoritmo, às vezes você vai preciso ser mais direto, cuidar do alinhamento você mesmo e usar o intrínseco da arquitetura explicitamente, por exemplo, AVX2:
#include <immintrin.h>
#include <stddef.h>
void add_float_avx2(size_t n, const float* a, const float* b, float* c)
{
size_t i = 0;
for (; i + 8 <= n; i += 8) {
__m256 va = _mm256_loadu_ps(a + i); // carrega 8 floats
__m256 vb = _mm256_loadu_ps(b + i); // carrega 8 floats
__m256 vc = _mm256_add_ps(va, vb); // soma 8 floats “em paralelo”
_mm256_storeu_ps(c + i, vc);
}
// calcula a rebarba
for (; i < n; ++i) {
c[i] = a[i] + b[i];
}
}