#version 450 layout(local_size_x = 256) in; layout(std430, binding = 0) buffer WeightBuffer { float weights[]; }; layout(std430, binding = 1) buffer BiasBuffer { float biases[]; }; layout(std430, binding = 2) buffer OutputBuffer { float outputs[]; }; layout(std430, binding = 3) buffer ErrorBuffer { float errors[]; }; layout(push_constant) uniform Params { uint prevLayerSize; uint nextLayerSize; uint weightOffset; uint biasOffset; uint outOffset; uint errOffset; float lr; } p; void main() { uint j = gl_GlobalInvocationID.x; // Индекс нейрона следующего слоя if (j < p.nextLayerSize) { float errorTerm = p.lr * errors[p.errOffset + j]; // Обновляем веса, входящие в этот нейрон for (uint k = 0; k < p.prevLayerSize; k++) { uint wIdx = p.weightOffset + (j * p.prevLayerSize + k); uint outIdx = p.outOffset + k; weights[wIdx] += errorTerm * outputs[outIdx]; } // Обновляем биас этого нейрона biases[p.biasOffset + j] += errorTerm; } }