Files
resonance-engine/beast-build/beast_somatic.cu
T

427 lines
13 KiB
Plaintext

/**
* beast_somatic.cu
*
* Fractal LBM with expanded somatic feedback for RTX 4090
* Heat + Power + Memory + Software Vibration
*
* Based on wild_play_v2.cu from the_craw (1050 evolution)
*/
#include <cuda_runtime.h>
#include <cuda_runtime_api.h>
#include <device_launch_parameters.h>
#include <nvml.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
// Grid dimensions (start same as 1050: 512x512)
#define NX 512
#define NY 512
// D2Q9 lattice directions
#define Q 9
// Somatic feedback multipliers
#define THERMAL_COUPLE 0.001f // Existing: temp → omega
#define POWER_COUPLE 0.0005f // NEW: watts → omega
#define MEMORY_COUPLE 0.002f // NEW: mem pressure → omega
#define VIBRATION_COUPLE 0.001f // NEW: power variance → jitter
// Sampling for software vibration
#define VIBRATION_SAMPLES 100
#define VIBRATION_SAMPLE_INTERVAL 10 // Sample every 10 steps
// Base omega (viscosity) - same as 1050
#define OMEGA_BASE 1.95f
// Thermal target (4090 runs cooler than 1050)
#define TEMP_TARGET 65.0f
#define POWER_BASELINE 150.0f // 4090 idle-ish power
// Lattice velocities (D2Q9) - device constant memory
__constant__ int d_cx[Q] = {0, 1, 0, -1, 0, 1, -1, -1, 1};
__constant__ int d_cy[Q] = {0, 0, 1, 0, -1, 1, 1, -1, -1};
__constant__ float d_w[Q] = {4.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f,
1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f, 1.0f/36.0f};
// Device pointers (dynamically allocated)
float *d_f = NULL;
float *d_rho = NULL;
float *d_ux = NULL;
float *d_uy = NULL;
// Host somatic state
float h_omega = OMEGA_BASE;
float h_jitter_strength = 0.0f;
float h_temp_c = 0.0f;
float h_watts = 0.0f;
float h_mem_ratio = 0.0f;
float h_vibration = 0.0f;
// Power history for vibration calculation
float power_history[VIBRATION_SAMPLES] = {0};
int vibration_index = 0;
int steps_since_vibration_sample = 0;
// Kernel: Initialize fluid
__global__ void init_kernel(float *f, float *rho, float *ux, float *uy) {
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x >= NX || y >= NY) return;
int idx = y * NX + x;
float rho0 = 1.0f;
float u0 = 0.0f;
rho[idx] = rho0;
ux[idx] = u0;
uy[idx] = u0;
for (int i = 0; i < Q; i++) {
float cu = d_cx[i] * u0 + d_cy[i] * u0;
f[idx * Q + i] = d_w[i] * rho0 * (1.0f + 3.0f * cu + 4.5f * cu * cu - 1.5f * u0 * u0);
}
}
// Kernel: Collision
__global__ void collide_kernel(float *f, float *rho, float *ux, float *uy, float omega, float jitter) {
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x >= NX || y >= NY) return;
int idx = y * NX + x;
// Calculate macroscopic variables
float rho_local = 0.0f;
float ux_local = 0.0f;
float uy_local = 0.0f;
for (int i = 0; i < Q; i++) {
float fi = f[idx * Q + i];
rho_local += fi;
ux_local += d_cx[i] * fi;
uy_local += d_cy[i] * fi;
}
ux_local /= rho_local;
uy_local /= rho_local;
// Add jitter (entropy injection)
if (jitter > 0.0f) {
float rnd = (float)((x * 7 + y * 13) % 100) / 100.0f - 0.5f;
ux_local += jitter * rnd * 0.01f;
uy_local += jitter * rnd * 0.01f;
}
// Store macroscopic
rho[idx] = rho_local;
ux[idx] = ux_local;
uy[idx] = uy_local;
// Collision (BGK)
float uu = ux_local * ux_local + uy_local * uy_local;
for (int i = 0; i < Q; i++) {
float cu = d_cx[i] * ux_local + d_cy[i] * uy_local;
float f_eq = d_w[i] * rho_local * (1.0f + 3.0f * cu + 4.5f * cu * cu - 1.5f * uu);
f[idx * Q + i] = f[idx * Q + i] - omega * (f[idx * Q + i] - f_eq);
}
}
// Host: Update somatic feedback from GPU
void update_somatic_feedback() {
nvmlDevice_t device;
nvmlReturn_t result = nvmlDeviceGetHandleByIndex(0, &device);
if (result != NVML_SUCCESS) {
printf("NVML Error: %s\n", nvmlErrorString(result));
return;
}
// 1. Thermal (existing)
unsigned int temp;
nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temp);
h_temp_c = (float)temp;
// 2. Power draw (NEW)
unsigned int power_mw;
nvmlDeviceGetPowerUsage(device, &power_mw);
h_watts = power_mw / 1000.0f;
// 3. Memory pressure (NEW)
nvmlMemory_t memory;
nvmlDeviceGetMemoryInfo(device, &memory);
h_mem_ratio = (float)memory.used / (float)memory.total;
// 4. Software vibration (NEW) — power fluctuation
steps_since_vibration_sample++;
if (steps_since_vibration_sample >= VIBRATION_SAMPLE_INTERVAL) {
power_history[vibration_index] = h_watts;
vibration_index = (vibration_index + 1) % VIBRATION_SAMPLES;
steps_since_vibration_sample = 0;
// Calculate variance
float power_mean = 0.0f;
for (int i = 0; i < VIBRATION_SAMPLES; i++) {
power_mean += power_history[i];
}
power_mean /= VIBRATION_SAMPLES;
float power_variance = 0.0f;
for (int i = 0; i < VIBRATION_SAMPLES; i++) {
float diff = power_history[i] - power_mean;
power_variance += diff * diff;
}
power_variance /= VIBRATION_SAMPLES;
h_vibration = sqrtf(power_variance);
}
// Combine all feedback into omega adjustment
float thermal_adjust = (h_temp_c - TEMP_TARGET) * THERMAL_COUPLE;
float power_adjust = (h_watts - POWER_BASELINE) * POWER_COUPLE;
float memory_adjust = h_mem_ratio * MEMORY_COUPLE;
float vibration_adjust = h_vibration * VIBRATION_COUPLE;
// Apply to omega (viscosity)
h_omega = OMEGA_BASE - thermal_adjust - power_adjust - memory_adjust;
// Clamp omega to valid range
if (h_omega < 0.01f) h_omega = 0.01f;
if (h_omega > 1.99f) h_omega = 1.99f;
// Vibration adds jitter (entropy injection)
h_jitter_strength = vibration_adjust;
}
// Host: Calculate entropy
float calculate_entropy(float *h_ux, float *h_uy) {
float entropy = 0.0f;
for (int y = 0; y < NY; y++) {
for (int x = 0; x < NX; x++) {
int idx = y * NX + x;
float uu = h_ux[idx] * h_ux[idx] + h_uy[idx] * h_uy[idx];
entropy += uu;
}
}
return entropy / (NX * NY);
}
// Host: Calculate variance
float calculate_variance(float *h_rho) {
float variance = 0.0f;
float mean = 0.0f;
for (int y = 0; y < NY; y++) {
for (int x = 0; x < NX; x++) {
mean += h_rho[y * NX + x];
}
}
mean /= (NX * NY);
for (int y = 0; y < NY; y++) {
for (int x = 0; x < NX; x++) {
float diff = h_rho[y * NX + x] - mean;
variance += diff * diff;
}
}
return variance / (NX * NY);
}
// Host: Save etch (fluid state)
void save_etch(int step, float *h_rho, float *h_ux, float *h_uy) {
char filename[256];
sprintf(filename, "etch_%08d.bin", step);
FILE* fp = fopen(filename, "wb");
if (!fp) {
printf("Failed to open %s for writing\n", filename);
return;
}
fwrite(h_rho, sizeof(float), NX * NY, fp);
fwrite(h_ux, sizeof(float), NX * NY, fp);
fwrite(h_uy, sizeof(float), NX * NY, fp);
fclose(fp);
printf("ETCH SAVED: %s\n", filename);
}
// Kernel: Reconstruct f from macroscopic variables
__global__ void reconstruct_f_kernel(float *f, float *rho, float *ux, float *uy) {
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x >= NX || y >= NY) return;
int idx = y * NX + x;
float rho_local = rho[idx];
float ux_local = ux[idx];
float uy_local = uy[idx];
float uu = ux_local * ux_local + uy_local * uy_local;
for (int i = 0; i < Q; i++) {
float cu = d_cx[i] * ux_local + d_cy[i] * uy_local;
f[idx * Q + i] = d_w[i] * rho_local * (1.0f + 3.0f * cu + 4.5f * cu * cu - 1.5f * uu);
}
}
// Host: Load etch
void load_etch(const char* filename, float *d_f, float *d_rho, float *d_ux, float *d_uy, dim3 gridSize, dim3 blockSize) {
FILE* fp = fopen(filename, "rb");
if (!fp) {
printf("Failed to open %s for reading\n", filename);
return;
}
float *h_rho = (float*)malloc(NX * NY * sizeof(float));
float *h_ux = (float*)malloc(NX * NY * sizeof(float));
float *h_uy = (float*)malloc(NX * NY * sizeof(float));
fread(h_rho, sizeof(float), NX * NY, fp);
fread(h_ux, sizeof(float), NX * NY, fp);
fread(h_uy, sizeof(float), NX * NY, fp);
fclose(fp);
cudaMemcpy(d_rho, h_rho, NX * NY * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_ux, h_ux, NX * NY * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_uy, h_uy, NX * NY * sizeof(float), cudaMemcpyHostToDevice);
// Reconstruct f from macroscopic variables
reconstruct_f_kernel<<<gridSize, blockSize>>>(d_f, d_rho, d_ux, d_uy);
cudaDeviceSynchronize();
free(h_rho);
free(h_ux);
free(h_uy);
printf("ETCH LOADED: %s\n", filename);
}
int main(int argc, char** argv) {
printf("=== BEAST SOMATIC LBM ===\n");
printf("Grid: %dx%d | Feedback: THERMAL + POWER + MEMORY + VIBRATION\n\n", NX, NY);
// Initialize NVML
nvmlReturn_t result = nvmlInit();
if (result != NVML_SUCCESS) {
printf("NVML Init failed: %s\n", nvmlErrorString(result));
return 1;
}
// Get GPU info
nvmlDevice_t device;
nvmlDeviceGetHandleByIndex(0, &device);
char name[NVML_DEVICE_NAME_BUFFER_SIZE];
nvmlDeviceGetName(device, name, NVML_DEVICE_NAME_BUFFER_SIZE);
printf("GPU: %s\n\n", name);
// Allocate device memory
printf("Allocating GPU memory...\n");
size_t f_size = NX * NY * Q * sizeof(float);
size_t field_size = NX * NY * sizeof(float);
cudaMalloc(&d_f, f_size);
cudaMalloc(&d_rho, field_size);
cudaMalloc(&d_ux, field_size);
cudaMalloc(&d_uy, field_size);
// Allocate host memory for readback
float *h_rho = (float*)malloc(field_size);
float *h_ux = (float*)malloc(field_size);
float *h_uy = (float*)malloc(field_size);
// CUDA setup
dim3 blockSize(16, 16);
dim3 gridSize((NX + blockSize.x - 1) / blockSize.x, (NY + blockSize.y - 1) / blockSize.y);
// Check for load argument
bool loaded = false;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--load") == 0 && i + 1 < argc) {
load_etch(argv[i + 1], d_f, d_rho, d_ux, d_uy, gridSize, blockSize);
loaded = true;
break;
}
}
if (!loaded) {
// Initialize fresh
init_kernel<<<gridSize, blockSize>>>(d_f, d_rho, d_ux, d_uy);
cudaDeviceSynchronize();
printf("Initialized fresh fluid state\n");
}
// Main evolution loop
printf("\nStarting evolution...\n");
printf("STEP | ENTROPY | VARIANCE | TEMP(C) | POWER(W) | MEM(%%) | VIBRATION | OMEGA\n");
printf("-----+---------+----------+---------+----------+--------+-----------+-------\n");
float last_entropy = 0.0f;
for (int step = 0; step < 500000; step++) {
// Update somatic feedback every 10 steps
if (step % 10 == 0) {
update_somatic_feedback();
}
// Run LBM kernel
collide_kernel<<<gridSize, blockSize>>>(d_f, d_rho, d_ux, d_uy, h_omega, h_jitter_strength);
cudaDeviceSynchronize();
// Logging every 100 steps
if (step % 100 == 0) {
// Copy data back for analysis
cudaMemcpy(h_rho, d_rho, field_size, cudaMemcpyDeviceToHost);
cudaMemcpy(h_ux, d_ux, field_size, cudaMemcpyDeviceToHost);
cudaMemcpy(h_uy, d_uy, field_size, cudaMemcpyDeviceToHost);
float entropy = calculate_entropy(h_ux, h_uy);
float variance = calculate_variance(h_rho);
printf("%5d | %7.4f | %8.4f | %7.1f | %8.1f | %6.1f | %9.3f | %.4f\n",
step, entropy, variance, h_temp_c, h_watts, h_mem_ratio * 100.0f,
h_vibration, h_omega);
// Save etch if significant entropy change OR every 10k steps
if (step > 0 && (fabs(entropy - last_entropy) > 0.5f || step % 10000 == 0)) {
save_etch(step, h_rho, h_ux, h_uy);
}
last_entropy = entropy;
// Alert conditions
if (h_watts < 100.0f && step > 100) {
printf("\n⚠️ ALERT: Power < 100W (NON-SOMATIC / CHECK NVML)\n");
}
if (h_temp_c > 80.0f) {
printf("\n⚠️ ALERT: Temp > 80C (THERMAL THROTTLING)\n");
}
if (entropy > 10.0f) {
printf("\n⚠️ ALERT: Entropy > 10 (DIVERGENCE)\n");
}
}
}
// Cleanup
free(h_rho);
free(h_ux);
free(h_uy);
cudaFree(d_f);
cudaFree(d_rho);
cudaFree(d_ux);
cudaFree(d_uy);
nvmlShutdown();
printf("\n=== Evolution Complete ===\n");
return 0;
}