Implemented vulkan cross_entropy_loss and cross_entropy_loss_back (#27216)
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#version 450
|
||||
|
||||
#include "generic_head.glsl"
|
||||
#include "types.glsl"
|
||||
|
||||
#extension GL_EXT_control_flow_attributes : enable
|
||||
|
||||
layout(constant_id = 0) const uint BLOCK_SIZE = 32;
|
||||
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
|
||||
layout (binding = 1) readonly buffer B {B_TYPE data_b[];};
|
||||
layout (binding = 2) writeonly buffer D {D_TYPE data_d[];};
|
||||
|
||||
shared FLOAT_TYPE tmp[BLOCK_SIZE];
|
||||
|
||||
FLOAT_TYPE wg_reduce_max(FLOAT_TYPE v) {
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
tmp[tid] = v;
|
||||
barrier();
|
||||
[[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) {
|
||||
if (tid < s) {
|
||||
tmp[tid] = max(tmp[tid], tmp[tid + s]);
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
v = tmp[0];
|
||||
barrier();
|
||||
return v;
|
||||
}
|
||||
|
||||
FLOAT_TYPE wg_reduce_sum(FLOAT_TYPE v) {
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
tmp[tid] = v;
|
||||
barrier();
|
||||
[[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) {
|
||||
if (tid < s) {
|
||||
tmp[tid] += tmp[tid + s];
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
v = tmp[0];
|
||||
barrier();
|
||||
return v;
|
||||
}
|
||||
|
||||
void main() {
|
||||
const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x;
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
|
||||
if (row >= p.KY) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint off = row * p.KX;
|
||||
|
||||
FLOAT_TYPE max_logit = FLOAT_TYPE(uintBitsToFloat(0xFF800000));
|
||||
for (uint i = tid; i < p.KX; i += BLOCK_SIZE) {
|
||||
max_logit = max(max_logit, FLOAT_TYPE(data_a[off + i]));
|
||||
}
|
||||
max_logit = wg_reduce_max(max_logit);
|
||||
|
||||
FLOAT_TYPE sum_exp = FLOAT_TYPE(0.0f);
|
||||
for (uint i = tid; i < p.KX; i += BLOCK_SIZE) {
|
||||
sum_exp += exp(FLOAT_TYPE(data_a[off + i]) - max_logit);
|
||||
}
|
||||
const FLOAT_TYPE log_sum = log(wg_reduce_sum(sum_exp));
|
||||
|
||||
FLOAT_TYPE loss = FLOAT_TYPE(0.0f);
|
||||
for (uint i = tid; i < p.KX; i += BLOCK_SIZE) {
|
||||
loss += (FLOAT_TYPE(data_a[off + i]) - max_logit - log_sum) * FLOAT_TYPE(data_b[off + i]);
|
||||
}
|
||||
loss = -wg_reduce_sum(loss) / FLOAT_TYPE(p.KY);
|
||||
|
||||
if (tid == 0) {
|
||||
data_d[row] = D_TYPE(loss);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#version 450
|
||||
|
||||
#include "generic_head.glsl"
|
||||
#include "types.glsl"
|
||||
|
||||
#extension GL_EXT_control_flow_attributes : enable
|
||||
|
||||
layout(constant_id = 0) const uint BLOCK_SIZE = 32;
|
||||
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout (binding = 0) readonly buffer G {A_TYPE data_g[];};
|
||||
layout (binding = 1) readonly buffer X {B_TYPE data_x[];};
|
||||
layout (binding = 2) readonly buffer Y {B_TYPE data_y[];};
|
||||
layout (binding = 3) writeonly buffer D {D_TYPE data_d[];};
|
||||
|
||||
shared FLOAT_TYPE tmp[BLOCK_SIZE];
|
||||
|
||||
FLOAT_TYPE wg_reduce_max(FLOAT_TYPE v) {
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
tmp[tid] = v;
|
||||
barrier();
|
||||
[[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) {
|
||||
if (tid < s) {
|
||||
tmp[tid] = max(tmp[tid], tmp[tid + s]);
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
v = tmp[0];
|
||||
barrier();
|
||||
return v;
|
||||
}
|
||||
|
||||
FLOAT_TYPE wg_reduce_sum(FLOAT_TYPE v) {
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
tmp[tid] = v;
|
||||
barrier();
|
||||
[[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) {
|
||||
if (tid < s) {
|
||||
tmp[tid] += tmp[tid + s];
|
||||
}
|
||||
barrier();
|
||||
}
|
||||
v = tmp[0];
|
||||
barrier();
|
||||
return v;
|
||||
}
|
||||
|
||||
void main() {
|
||||
const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x;
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
|
||||
if (row >= p.KY) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint off = row * p.KX;
|
||||
const FLOAT_TYPE d_by_nrows = FLOAT_TYPE(data_g[0]) / FLOAT_TYPE(p.KY);
|
||||
|
||||
FLOAT_TYPE max_logit = FLOAT_TYPE(uintBitsToFloat(0xFF800000));
|
||||
for (uint i = tid; i < p.KX; i += BLOCK_SIZE) {
|
||||
max_logit = max(max_logit, FLOAT_TYPE(data_x[off + i]));
|
||||
}
|
||||
max_logit = wg_reduce_max(max_logit);
|
||||
|
||||
FLOAT_TYPE sum_exp = FLOAT_TYPE(0.0f);
|
||||
for (uint i = tid; i < p.KX; i += BLOCK_SIZE) {
|
||||
sum_exp += exp(FLOAT_TYPE(data_x[off + i]) - max_logit);
|
||||
}
|
||||
const FLOAT_TYPE inv_sum = FLOAT_TYPE(1.0f) / wg_reduce_sum(sum_exp);
|
||||
|
||||
for (uint i = tid; i < p.KX; i += BLOCK_SIZE) {
|
||||
const FLOAT_TYPE sm = exp(FLOAT_TYPE(data_x[off + i]) - max_logit) * inv_sum;
|
||||
data_d[off + i] = D_TYPE((sm - FLOAT_TYPE(data_y[off + i])) * d_by_nrows);
|
||||
}
|
||||
}
|
||||
@@ -1029,6 +1029,8 @@ void process_shaders() {
|
||||
|
||||
string_to_spv("argmax_f32", "argmax.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "int"}}));
|
||||
string_to_spv("sum_rows_f32", "sum_rows.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("cross_entropy_loss_f32", "cross_entropy_loss.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("cross_entropy_loss_back_f32", "cross_entropy_loss_back.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("fwht_f32", "fwht.comp", {});
|
||||
string_to_spv("fwht_shmem_f32", "fwht.comp", {{"FWHT_SHMEM", "1"}});
|
||||
string_to_spv("count_equal_i32", "count_equal.comp", merge_maps(base_dict, {{"A_TYPE", "int"}, {"B_TYPE", "int"}, {"D_TYPE", "int"}}));
|
||||
|
||||
Reference in New Issue
Block a user