#version 430

// Ultra-performance monitoring compute shader
// Real-time performance analytics and adaptive optimization recommendations

layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;

// Performance metrics input
layout(std430, binding = 0) buffer TimingBuffer {
    float execution_times[];    // Microseconds per operation
};

layout(std430, binding = 1) buffer ThroughputBuffer {
    float throughput_data[];    // Operations per second
};

layout(std430, binding = 2) buffer MemoryMetricsBuffer {
    float memory_metrics[];     // [allocated, used, bandwidth_util, cache_hit_rate]
};

layout(std430, binding = 3) buffer ComputeMetricsBuffer {
    float compute_metrics[];    // [gpu_util, shader_occupancy, warp_efficiency]
};

// Historical performance data
layout(std430, binding = 4) buffer PerformanceHistoryBuffer {
    float perf_history[];       // Last 32 measurements per metric
};

// Anomaly detection thresholds
layout(std430, binding = 5) buffer ThresholdsBuffer {
    float thresholds[];         // [min_throughput, max_memory, max_latency, min_efficiency]
};

// Output: optimization recommendations
layout(std430, binding = 6) buffer RecommendationsBuffer {
    int recommendations[];      // Bitfield of optimization recommendations
};

// Output: performance predictions
layout(std430, binding = 7) buffer PredictionsBuffer {
    float predictions[];        // Predicted performance metrics
};

// Output: anomaly flags
layout(std430, binding = 8) buffer AnomalyBuffer {
    int anomaly_flags[];        // Detected anomalies
};

uniform int num_systems;
uniform float time_window;          // Time window for analysis (seconds)
uniform float anomaly_sensitivity;  // Sensitivity for anomaly detection
uniform bool enable_ml_prediction;  // Enable ML-based prediction
uniform bool enable_auto_tuning;    // Enable automatic optimization

// Shared memory for statistical computations
shared float shared_metrics[128 * 8];
shared float shared_stats[128];

// Optimization recommendation flags
const int RECOMMENDATION_REDUCE_PRECISION = 1;
const int RECOMMENDATION_INCREASE_BATCH_SIZE = 2;
const int RECOMMENDATION_ENABLE_CACHING = 4;
const int RECOMMENDATION_ADJUST_BLOCK_SIZE = 8;
const int RECOMMENDATION_SWITCH_ALGORITHM = 16;
const int RECOMMENDATION_REDUCE_MEMORY_USAGE = 32;
const int RECOMMENDATION_INCREASE_PARALLELISM = 64;
const int RECOMMENDATION_OPTIMIZE_MEMORY_LAYOUT = 128;

// Anomaly detection flags
const int ANOMALY_PERFORMANCE_DEGRADATION = 1;
const int ANOMALY_MEMORY_SPIKE = 2;
const int ANOMALY_COMPUTE_UNDERUTILIZATION = 4;
const int ANOMALY_CACHE_THRASHING = 8;
const int ANOMALY_BANDWIDTH_SATURATION = 16;

// Simple moving average calculation
float moving_average(float data[], int start_idx, int window_size) {
    float sum = 0.0;
    int count = 0;
    
    for (int i = 0; i < window_size; i++) {
        int idx = start_idx + i;
        if (data[idx] > 0.0) {
            sum += data[idx];
            count++;
        }
    }
    
    return count > 0 ? sum / float(count) : 0.0;
}

// Standard deviation calculation
float standard_deviation(float data[], int start_idx, int window_size, float mean) {
    float sum_sq_diff = 0.0;
    int count = 0;
    
    for (int i = 0; i < window_size; i++) {
        int idx = start_idx + i;
        if (data[idx] > 0.0) {
            float diff = data[idx] - mean;
            sum_sq_diff += diff * diff;
            count++;
        }
    }
    
    return count > 1 ? sqrt(sum_sq_diff / float(count - 1)) : 0.0;
}

// ML-based performance prediction (simplified neural network)
float predict_performance(uint system_id, float features[8]) {
    // Simple 3-layer neural network prediction
    float hidden1[4];
    float hidden2[2];
    
    // First hidden layer (8 -> 4)
    float weights1[32] = float[32](
        0.5, -0.3, 0.8, 0.2, -0.6, 0.4, 0.7, -0.1,  // hidden1[0]
        -0.2, 0.6, -0.4, 0.9, 0.1, -0.7, 0.3, 0.5,  // hidden1[1]
        0.7, 0.1, -0.5, 0.8, -0.2, 0.6, -0.3, 0.4,  // hidden1[2]
        -0.4, 0.8, 0.2, -0.6, 0.5, 0.1, -0.7, 0.3   // hidden1[3]
    );
    
    for (int i = 0; i < 4; i++) {
        float sum = 0.0;
        for (int j = 0; j < 8; j++) {
            sum += features[j] * weights1[i * 8 + j];
        }
        hidden1[i] = max(0.0, sum);  // ReLU activation
    }
    
    // Second hidden layer (4 -> 2)
    float weights2[8] = float[8](
        0.6, -0.4, 0.8, 0.2,  // hidden2[0]
        -0.3, 0.7, -0.1, 0.5  // hidden2[1]
    );
    
    for (int i = 0; i < 2; i++) {
        float sum = 0.0;
        for (int j = 0; j < 4; j++) {
            sum += hidden1[j] * weights2[i * 4 + j];
        }
        hidden2[i] = max(0.0, sum);  // ReLU activation
    }
    
    // Output layer (2 -> 1)
    float output_weights[2] = float[2](0.8, -0.3);
    float output = 0.0;
    for (int i = 0; i < 2; i++) {
        output += hidden2[i] * output_weights[i];
    }
    
    return 1.0 / (1.0 + exp(-output));  // Sigmoid activation
}

void main() {
    uint index = gl_GlobalInvocationID.x;
    uint tid = gl_LocalInvocationID.x;
    
    if (index >= num_systems) return;
    
    // Load current performance metrics
    float current_exec_time = execution_times[index];
    float current_throughput = throughput_data[index];
    
    // Memory metrics: [allocated, used, bandwidth_util, cache_hit_rate]
    float mem_allocated = memory_metrics[index * 4 + 0];
    float mem_used = memory_metrics[index * 4 + 1];
    float bandwidth_util = memory_metrics[index * 4 + 2];
    float cache_hit_rate = memory_metrics[index * 4 + 3];
    
    // Compute metrics: [gpu_util, shader_occupancy, warp_efficiency]
    float gpu_util = compute_metrics[index * 3 + 0];
    float shader_occupancy = compute_metrics[index * 3 + 1];
    float warp_efficiency = compute_metrics[index * 3 + 2];
    
    // Calculate historical statistics
    int hist_start = index * 32;
    float avg_throughput = moving_average(perf_history, hist_start, 16);
    float std_throughput = standard_deviation(perf_history, hist_start, 16, avg_throughput);
    
    // Anomaly detection
    int anomalies = 0;
    
    // Performance degradation
    if (current_throughput < avg_throughput - 2.0 * std_throughput * anomaly_sensitivity) {
        anomalies |= ANOMALY_PERFORMANCE_DEGRADATION;
    }
    
    // Memory spike
    float memory_usage_ratio = mem_used / max(mem_allocated, 1.0);
    if (memory_usage_ratio > thresholds[1]) {
        anomalies |= ANOMALY_MEMORY_SPIKE;
    }
    
    // Compute underutilization
    if (gpu_util < thresholds[3]) {
        anomalies |= ANOMALY_COMPUTE_UNDERUTILIZATION;
    }
    
    // Cache thrashing
    if (cache_hit_rate < 0.5) {
        anomalies |= ANOMALY_CACHE_THRASHING;
    }
    
    // Bandwidth saturation
    if (bandwidth_util > 0.95) {
        anomalies |= ANOMALY_BANDWIDTH_SATURATION;
    }
    
    anomaly_flags[index] = anomalies;
    
    // Generate optimization recommendations
    int recommendations = 0;
    
    if (enable_auto_tuning) {
        // Reduce precision if performance is poor and accuracy allows
        if ((anomalies & ANOMALY_PERFORMANCE_DEGRADATION) && current_exec_time > thresholds[2]) {
            recommendations |= RECOMMENDATION_REDUCE_PRECISION;
        }
        
        // Increase batch size if underutilizing compute
        if (anomalies & ANOMALY_COMPUTE_UNDERUTILIZATION) {
            recommendations |= RECOMMENDATION_INCREASE_BATCH_SIZE;
        }
        
        // Enable caching if cache hit rate is low
        if (anomalies & ANOMALY_CACHE_THRASHING) {
            recommendations |= RECOMMENDATION_ENABLE_CACHING;
            recommendations |= RECOMMENDATION_OPTIMIZE_MEMORY_LAYOUT;
        }
        
        // Reduce memory usage if memory spike detected
        if (anomalies & ANOMALY_MEMORY_SPIKE) {
            recommendations |= RECOMMENDATION_REDUCE_MEMORY_USAGE;
        }
        
        // Adjust block size if bandwidth is saturated
        if (anomalies & ANOMALY_BANDWIDTH_SATURATION) {
            recommendations |= RECOMMENDATION_ADJUST_BLOCK_SIZE;
        }
        
        // Switch algorithm if performance consistently poor
        if (current_throughput < avg_throughput * 0.5) {
            recommendations |= RECOMMENDATION_SWITCH_ALGORITHM;
        }
    }
    
    recommendations_buffer[index] = recommendations;
    
    // ML-based performance prediction
    if (enable_ml_prediction) {
        float features[8] = float[8](
            current_throughput / 1000.0,    // Normalized throughput
            current_exec_time / 1000.0,     // Normalized execution time
            memory_usage_ratio,              // Memory usage ratio
            bandwidth_util,                  // Bandwidth utilization
            cache_hit_rate,                  // Cache hit rate
            gpu_util,                        // GPU utilization
            shader_occupancy,                // Shader occupancy
            warp_efficiency                  // Warp efficiency
        );
        
        float predicted_perf = predict_performance(index, features);
        predictions[index] = predicted_perf;
    } else {
        // Simple linear prediction based on trend
        float trend = (current_throughput - avg_throughput) / max(avg_throughput, 1.0);
        predictions[index] = current_throughput * (1.0 + trend * 0.1);
    }
    
    // Update performance history (circular buffer)
    int hist_idx = hist_start + (int(gl_GlobalInvocationID.x) % 32);
    perf_history[hist_idx] = current_throughput;
}