Files
fn_registry/cpp/functions/gfx/gpu_rng_glsl.md
T
egutierrez c74fd4ae0d feat(cpp/gfx): GPU compute primitives for Monte Carlo (G1-G7)
Stack base de compute shaders OpenGL 4.3 para cargas Monte Carlo intensivas
en GPU. Reutiliza el patron de graph_force_layout_gpu (SSBO + compute) y se
integra con el resto del registry sin nuevos simbolos en gl_loader (todo lo
que se necesita ya estaba expuesto).

- gpu_ssbo: lifecycle de Shader Storage Buffer Objects.
- gpu_compute_program: compila compute GLSL 4.3 con preamble inyectable
  (mismo pattern de gl_shader::compile_fragment).
- gpu_dispatch: dispatch_1d/2d/3d con ceil(N/local) automatico + barrier
  helpers (storage, uniform, image, buffer_update, all).
- gpu_rng_glsl: PCG32 GLSL (uniform/normal/below) + SplitMix64 seed walkers
  para sembrar deterministicamente N walkers desde un master seed.
- gpu_histogram_1d: SSBO float[N] -> uint[nbins] via atomicAdd.
- gpu_histogram_2d: SSBO float[2N] xy-interleaved -> uint[nx*ny] +
  to_density helper para alimentar heatmap_cpp_viz.
- gpu_reduce: workgroup-shared sum/min/max/mean (local 256, partials CPU).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 11:52:08 +02:00

4.0 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, framework, params, output
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path framework params output
gpu_rng_glsl function cpp gfx 1.0.0 pure std::string glsl_rng_preamble(int seed_binding); void seed_walkers_init(uint64_t master_seed, uint32_t* out, int count) Generador de preamble GLSL con primitivas PCG32 (uniform, normal, below) inyectables en compute shaders, mas helper CPU para sembrar N seeds deterministas via SplitMix64. Sin GL ni I/O — funciones puras que producen string y rellenan array.
glsl
rng
pcg32
splitmix64
montecarlo
compute
gpu
gfx
false
string
cstdint
cstdio
false
cpp/functions/gfx/gpu_rng_glsl.cpp opengl
name desc
seed_binding Indice del binding std430 donde reside el SSBO uint rng_seeds[]. Tipicamente reservar el ultimo binding del shader (8 o 9).
name desc
master_seed Semilla maestra de la que se derivan todas las semillas individuales. 0 se sustituye por la constante de Knuth para evitar arranques degenerados.
name desc
out Buffer destino de count uint32. Garantiza out[i] != 0 (requisito de PCG32).
name desc
count Numero de semillas a generar. Igual al numero de threads/walkers que ejecutaran el compute.
glsl_rng_preamble: string GLSL listo para concatenar como preamble de compile_compute. seed_walkers_init: rellena out[count] in-place. Ambas son puras.

gpu_rng_glsl

Pareja CPU + GLSL para Monte Carlo en compute shaders.

Calidad

PCG32 (variante recomendada por O'Neill, 2014) tiene state de 32 bits, periodo 2^32 por chain y supera los tests de PractRand hasta varios TB. Para Monte Carlo no criptografico es la opcion estandar moderna. Cada thread tiene su propio state independiente (sin contention atomico), asi que el periodo agregado de N chains es N · 2^32 — mas que suficiente para 10^10 samples.

rng_normal usa Box-Muller con cos (descarta la sin) — ~30 ciclos GPU por sample, un orden de magnitud mas barato que el Ziggurat y sin tablas de lookup que machacarian el cache.

API GLSL inyectada por glsl_rng_preamble

layout(std430, binding = <seed_binding>) buffer RngSeeds { uint rng_seeds[]; };

uint  pcg32       (inout uint state);
float rng_uniform (inout uint state);              // [0, 1)
float rng_normal  (inout uint state);              // N(0, 1)
uint  rng_below   (inout uint state, uint n);      // [0, n) sin sesgo

Patron de uso

CPU:

std::vector<unsigned int> seeds(N);
fn::gfx::seed_walkers_init(0xC0FFEE, seeds.data(), N);

fn::gfx::Ssbo seed_ssbo = fn::gfx::ssbo_create(
    N * sizeof(unsigned int), seeds.data(), GL_DYNAMIC_COPY);

auto rng_src = fn::gfx::glsl_rng_preamble(/*seed_binding=*/9);
auto r = fn::gfx::compile_compute(my_body, 64, rng_src);

GLSL (my_body):

layout(std430, binding = 0) buffer Out { float samples[]; };
uniform uint u_count;

void main() {
    uint i = gl_GlobalInvocationID.x;
    if (i >= u_count) return;

    uint s = rng_seeds[i];
    samples[i] = rng_normal(s);
    rng_seeds[i] = s;   // persistir para el siguiente dispatch
}

Despacho:

glUseProgram(r.program);
fn::gfx::ssbo_bind(out_ssbo,  0);
fn::gfx::ssbo_bind(seed_ssbo, 9);
glUniform1ui(loc_count, N);
fn::gfx::dispatch_1d(N, 64);
fn::gfx::barrier_storage();

Notas

  • El binding del SSBO de seeds es parametro porque cada shader puede usar bindings distintos para sus datos. Convencion sugerida: el ultimo binding del shader (8 o 9).
  • Para reproducibilidad bit-exacta entre runs, mantener master_seed y N constantes; los samples seran identicos. Util para tests numericos.
  • seed_walkers_init es deterministica y no depende de GL — se puede invocar en tests unitarios CPU sin contexto OpenGL.
  • Para muestreo categorico (sampleTier de vr_tiered_lab) usar rng_uniform con cumulative-sum manual en el shader; un helper dedicado se puede añadir si aparece en multiples kernels.