mirror of
https://github.com/ggerganov/whisper.cpp.git
synced 2025-05-01 22:54:53 +02:00
opencl: Fix rope and softmax (llama/11833)
* opencl: fix `ROPE` * opencl: fix `SOFT_MAX` * Add fp16 variant * opencl: enforce subgroup size for `soft_max`
This commit is contained in:
parent
47cc043e69
commit
4b48fe449a
@ -143,6 +143,7 @@ struct ggml_backend_opencl_context {
|
|||||||
cl_kernel kernel_rms_norm;
|
cl_kernel kernel_rms_norm;
|
||||||
cl_kernel kernel_diag_mask_inf, kernel_diag_mask_inf_8;
|
cl_kernel kernel_diag_mask_inf, kernel_diag_mask_inf_8;
|
||||||
cl_kernel kernel_soft_max, kernel_soft_max_4;
|
cl_kernel kernel_soft_max, kernel_soft_max_4;
|
||||||
|
cl_kernel kernel_soft_max_f16, kernel_soft_max_4_f16;
|
||||||
cl_kernel kernel_get_rows_f32, kernel_get_rows_f16, kernel_get_rows_q4_0;
|
cl_kernel kernel_get_rows_f32, kernel_get_rows_f16, kernel_get_rows_q4_0;
|
||||||
cl_kernel kernel_rope_norm_f32, kernel_rope_norm_f16, kernel_rope_neox_f32, kernel_rope_neox_f16;
|
cl_kernel kernel_rope_norm_f32, kernel_rope_norm_f16, kernel_rope_neox_f32, kernel_rope_neox_f16;
|
||||||
cl_kernel kernel_cpy_f16_f16, kernel_cpy_f16_f32, kernel_cpy_f32_f16, kernel_cpy_f32_f32;
|
cl_kernel kernel_cpy_f16_f16, kernel_cpy_f16_f32, kernel_cpy_f32_f16, kernel_cpy_f32_f32;
|
||||||
@ -614,6 +615,8 @@ static ggml_backend_opencl_context * ggml_cl2_init(ggml_backend_dev_t dev) {
|
|||||||
CL_CHECK((backend_ctx->kernel_diag_mask_inf_8 = clCreateKernel(backend_ctx->program, "kernel_diag_mask_inf_8", &err), err));
|
CL_CHECK((backend_ctx->kernel_diag_mask_inf_8 = clCreateKernel(backend_ctx->program, "kernel_diag_mask_inf_8", &err), err));
|
||||||
CL_CHECK((backend_ctx->kernel_soft_max = clCreateKernel(backend_ctx->program, "kernel_soft_max", &err), err));
|
CL_CHECK((backend_ctx->kernel_soft_max = clCreateKernel(backend_ctx->program, "kernel_soft_max", &err), err));
|
||||||
CL_CHECK((backend_ctx->kernel_soft_max_4 = clCreateKernel(backend_ctx->program, "kernel_soft_max_4", &err), err));
|
CL_CHECK((backend_ctx->kernel_soft_max_4 = clCreateKernel(backend_ctx->program, "kernel_soft_max_4", &err), err));
|
||||||
|
CL_CHECK((backend_ctx->kernel_soft_max_f16 = clCreateKernel(backend_ctx->program, "kernel_soft_max_f16", &err), err));
|
||||||
|
CL_CHECK((backend_ctx->kernel_soft_max_4_f16 = clCreateKernel(backend_ctx->program, "kernel_soft_max_4_f16", &err), err));
|
||||||
CL_CHECK((backend_ctx->kernel_rope_norm_f32 = clCreateKernel(backend_ctx->program, "kernel_rope_norm_f32", &err), err));
|
CL_CHECK((backend_ctx->kernel_rope_norm_f32 = clCreateKernel(backend_ctx->program, "kernel_rope_norm_f32", &err), err));
|
||||||
CL_CHECK((backend_ctx->kernel_rope_norm_f16 = clCreateKernel(backend_ctx->program, "kernel_rope_norm_f16", &err), err));
|
CL_CHECK((backend_ctx->kernel_rope_norm_f16 = clCreateKernel(backend_ctx->program, "kernel_rope_norm_f16", &err), err));
|
||||||
CL_CHECK((backend_ctx->kernel_rope_neox_f32 = clCreateKernel(backend_ctx->program, "kernel_rope_neox_f32", &err), err));
|
CL_CHECK((backend_ctx->kernel_rope_neox_f32 = clCreateKernel(backend_ctx->program, "kernel_rope_neox_f32", &err), err));
|
||||||
@ -1044,8 +1047,16 @@ static bool ggml_opencl_supports_op(ggml_backend_dev_t dev, const struct ggml_te
|
|||||||
return true;
|
return true;
|
||||||
case GGML_OP_DIAG_MASK_INF:
|
case GGML_OP_DIAG_MASK_INF:
|
||||||
return op->ne[3] == 1;
|
return op->ne[3] == 1;
|
||||||
case GGML_OP_ROPE:
|
case GGML_OP_ROPE: {
|
||||||
|
const int mode = ((const int32_t *) op->op_params)[2];
|
||||||
|
if (mode & GGML_ROPE_TYPE_MROPE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mode & GGML_ROPE_TYPE_VISION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3666,6 +3677,8 @@ static void ggml_cl_soft_max(ggml_backend_t backend, const ggml_tensor * src0, c
|
|||||||
const float m0 = powf(2.0f, -(max_bias ) / n_head_log2);
|
const float m0 = powf(2.0f, -(max_bias ) / n_head_log2);
|
||||||
const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2);
|
const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2);
|
||||||
|
|
||||||
|
const bool use_f16 = (src1 && src1->type == GGML_TYPE_F16);
|
||||||
|
|
||||||
// Local size must be wave size. Each workgroup is a wave, working on a row,
|
// Local size must be wave size. Each workgroup is a wave, working on a row,
|
||||||
// where a row corresponds to leading dimension.
|
// where a row corresponds to leading dimension.
|
||||||
int nth = MIN(32, ne00);
|
int nth = MIN(32, ne00);
|
||||||
@ -3683,9 +3696,17 @@ static void ggml_cl_soft_max(ggml_backend_t backend, const ggml_tensor * src0, c
|
|||||||
cl_kernel kernel;
|
cl_kernel kernel;
|
||||||
|
|
||||||
if (ne00%4 == 0) {
|
if (ne00%4 == 0) {
|
||||||
kernel = backend_ctx->kernel_soft_max_4;
|
if (use_f16) {
|
||||||
|
kernel = backend_ctx->kernel_soft_max_4_f16;
|
||||||
|
} else {
|
||||||
|
kernel = backend_ctx->kernel_soft_max_4;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
kernel = backend_ctx->kernel_soft_max;
|
if (use_f16) {
|
||||||
|
kernel = backend_ctx->kernel_soft_max_f16;
|
||||||
|
} else {
|
||||||
|
kernel = backend_ctx->kernel_soft_max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CL_CHECK(clSetKernelArg(kernel, 0, sizeof(cl_mem), &extra0->data_device));
|
CL_CHECK(clSetKernelArg(kernel, 0, sizeof(cl_mem), &extra0->data_device));
|
||||||
@ -3766,7 +3787,8 @@ static void ggml_cl_rope(ggml_backend_t backend, const ggml_tensor * src0, const
|
|||||||
const int nb2 = dst ? dst->nb[2] : 0;
|
const int nb2 = dst ? dst->nb[2] : 0;
|
||||||
const int nb3 = dst ? dst->nb[3] : 0;
|
const int nb3 = dst ? dst->nb[3] : 0;
|
||||||
|
|
||||||
GGML_ASSERT(ne10 == ne02);
|
GGML_ASSERT(ne10 % ne02 == 0);
|
||||||
|
GGML_ASSERT(ne10 >= ne02);
|
||||||
|
|
||||||
int nth = MIN(64, ne00);
|
int nth = MIN(64, ne00);
|
||||||
|
|
||||||
|
@ -679,6 +679,9 @@ kernel void kernel_diag_mask_inf_8(
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// softmax
|
// softmax
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
#ifdef ADRENO_GPU
|
||||||
|
REQD_SUBGROUP_SIZE_64
|
||||||
|
#endif
|
||||||
kernel void kernel_soft_max(
|
kernel void kernel_soft_max(
|
||||||
global float * src0,
|
global float * src0,
|
||||||
ulong offset0,
|
ulong offset0,
|
||||||
@ -811,6 +814,141 @@ kernel void kernel_soft_max_4(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ADRENO_GPU
|
||||||
|
REQD_SUBGROUP_SIZE_64
|
||||||
|
#endif
|
||||||
|
kernel void kernel_soft_max_f16(
|
||||||
|
global float * src0,
|
||||||
|
ulong offset0,
|
||||||
|
global half * src1,
|
||||||
|
ulong offset1,
|
||||||
|
global float * dst,
|
||||||
|
ulong offsetd,
|
||||||
|
int ne00,
|
||||||
|
int ne01,
|
||||||
|
int ne02,
|
||||||
|
float scale,
|
||||||
|
float max_bias,
|
||||||
|
float m0,
|
||||||
|
float m1,
|
||||||
|
int n_head_log2
|
||||||
|
) {
|
||||||
|
src0 = (global float *)((global char *)src0 + offset0);
|
||||||
|
src1 = (global half *)((global char *)src1 + offset1);
|
||||||
|
dst = (global float *)((global char *)dst + offsetd);
|
||||||
|
|
||||||
|
int i03 = get_group_id(2);
|
||||||
|
int i02 = get_group_id(1);
|
||||||
|
int i01 = get_group_id(0);
|
||||||
|
|
||||||
|
global float * psrc0 = src0 + i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00;
|
||||||
|
global half * pmask = (global char *)src1 != (global char *)src0 ? src1 + i01*ne00 : 0;
|
||||||
|
global float * pdst = dst + i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00;
|
||||||
|
|
||||||
|
float slope = 1.0f;
|
||||||
|
|
||||||
|
// ALiBi
|
||||||
|
if (max_bias > 0.0f) {
|
||||||
|
int h = i02;
|
||||||
|
|
||||||
|
float base = h < n_head_log2 ? m0 : m1;
|
||||||
|
int exp = h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1;
|
||||||
|
|
||||||
|
slope = pow(base, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parallel max
|
||||||
|
float lmax = -INFINITY;
|
||||||
|
for (int i00 = get_local_id(0); i00 < ne00; i00 += get_local_size(0)) {
|
||||||
|
lmax = fmax(lmax, psrc0[i00]*scale + (pmask ? slope*pmask[i00] : 0.0f));
|
||||||
|
}
|
||||||
|
float max = sub_group_reduce_max(lmax);
|
||||||
|
|
||||||
|
// parallel sum
|
||||||
|
float lsum = 0.0f;
|
||||||
|
for (int i00 = get_local_id(0); i00 < ne00; i00 += get_local_size(0)) {
|
||||||
|
float exp_psrc0 = exp((psrc0[i00]*scale + (pmask ? slope*pmask[i00] : 0.0f)) - max);
|
||||||
|
lsum += exp_psrc0;
|
||||||
|
// Remember the result of exp here. exp is expensive, so we really do not
|
||||||
|
// wish to compute it twice.
|
||||||
|
pdst[i00] = exp_psrc0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float sum = sub_group_reduce_add(lsum);
|
||||||
|
|
||||||
|
for (int i00 = get_local_id(0); i00 < ne00; i00 += get_local_size(0)) {
|
||||||
|
pdst[i00] /= sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ADRENO_GPU
|
||||||
|
REQD_SUBGROUP_SIZE_64
|
||||||
|
#endif
|
||||||
|
kernel void kernel_soft_max_4_f16(
|
||||||
|
global float * src0,
|
||||||
|
ulong offset0,
|
||||||
|
global half * src1,
|
||||||
|
ulong offset1,
|
||||||
|
global float * dst,
|
||||||
|
ulong offsetd,
|
||||||
|
int ne00,
|
||||||
|
int ne01,
|
||||||
|
int ne02,
|
||||||
|
float scale,
|
||||||
|
float max_bias,
|
||||||
|
float m0,
|
||||||
|
float m1,
|
||||||
|
int n_head_log2
|
||||||
|
) {
|
||||||
|
src0 = (global float *)((global char *)src0 + offset0);
|
||||||
|
src1 = (global half *)((global char *)src1 + offset1);
|
||||||
|
dst = (global float *)((global char *)dst + offsetd);
|
||||||
|
|
||||||
|
int i03 = get_group_id(2);
|
||||||
|
int i02 = get_group_id(1);
|
||||||
|
int i01 = get_group_id(0);
|
||||||
|
|
||||||
|
global float4 * psrc4 = (global float4 *)(src0 + i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00);
|
||||||
|
global half4 * pmask = (global char *)src1 != (global char *)src0 ? (global half4 *)(src1 + i01*ne00) : 0;
|
||||||
|
global float4 * pdst4 = (global float4 *)(dst + i03*ne02*ne01*ne00 + i02*ne01*ne00 + i01*ne00);
|
||||||
|
|
||||||
|
float slope = 1.0f;
|
||||||
|
|
||||||
|
// ALiBi
|
||||||
|
if (max_bias > 0.0f) {
|
||||||
|
int h = i02;
|
||||||
|
|
||||||
|
float base = h < n_head_log2 ? m0 : m1;
|
||||||
|
int exp = h < n_head_log2 ? h + 1 : 2*(h - n_head_log2) + 1;
|
||||||
|
|
||||||
|
slope = pow(base, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parallel max
|
||||||
|
float4 lmax4 = -INFINITY;
|
||||||
|
for (int i00 = get_local_id(0); i00 < ne00/4; i00 += get_local_size(0)) {
|
||||||
|
lmax4 = fmax(lmax4, psrc4[i00]*scale + slope*(pmask ? convert_float4(pmask[i00]) : 0.0f));
|
||||||
|
}
|
||||||
|
float lmax = fmax(fmax(lmax4.s0, lmax4.s1), fmax(lmax4.s2, lmax4.s3));
|
||||||
|
|
||||||
|
const float max = sub_group_reduce_max(lmax);
|
||||||
|
|
||||||
|
// parallel sum
|
||||||
|
float4 lsum4 = 0.0f;
|
||||||
|
for (int i00 = get_local_id(0); i00 < ne00/4; i00 += get_local_size(0)) {
|
||||||
|
const float4 exp_psrc4 = exp((psrc4[i00]*scale + slope*(pmask ? convert_float4(pmask[i00]) : 0.0f)) - max);
|
||||||
|
lsum4 += exp_psrc4;
|
||||||
|
pdst4[i00] = exp_psrc4;
|
||||||
|
}
|
||||||
|
float lsum = lsum4.s0 + lsum4.s1 + lsum4.s2 + lsum4.s3;
|
||||||
|
|
||||||
|
const float sum = sub_group_reduce_add(lsum);
|
||||||
|
|
||||||
|
for (int i00 = get_local_id(0); i00 < ne00/4; i00 += get_local_size(0)) {
|
||||||
|
pdst4[i00] /= sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// kernel_rope
|
// kernel_rope
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user