* vulkan/cpu: Support f16 as SET_ROWS src.
This adds full support for f16 SET_ROWS (equivalent to f32) to vulkan and CPU
backends, and adds more backend tests.
* Set DenormPreserve 16 when supported, to try to fix failures on Intel
* tune error threshold
* update metal supports_op
cur = ggml_type_size(GGML_TYPE_F32) * node->src[0]->ne[0] * n_tasks;
}
} break;
+ case GGML_OP_SET_ROWS:
+ {
+ if (node->src[0]->type == GGML_TYPE_F16 && node->type != GGML_TYPE_F16) {
+ cur = ggml_type_size(GGML_TYPE_F32) * node->src[0]->ne[0] * n_tasks;
+ }
+ } break;
case GGML_OP_SOFT_MAX:
case GGML_OP_ROPE:
case GGML_OP_ROPE_BACK:
assert(ne0 == nc);
assert(ne2 == ne02);
assert(ne3 == ne03);
- GGML_ASSERT(src0->type == GGML_TYPE_F32 || (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16));
+ GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16);
assert(ne02 % ne11 == 0);
assert(ne03 % ne12 == 0);
(const float *) ((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03),
((char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3), nc);
} else if constexpr (std::is_same_v<src_t, ggml_fp16_t>) {
- memcpy(
+ if (dst->type == GGML_TYPE_F16) {
+ memcpy(
((char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3),
((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03),
rs);
+ } else {
+ float * wdata = (float *) params->wdata + (nc + CACHE_LINE_SIZE_F32) * ith;
+ ggml_fp16_to_fp32_row(
+ (const ggml_fp16_t *) ((char *) src0->data + i*nb01 + i02*nb02 + i03*nb03),
+ wdata, nc);
+ from_float(wdata,
+ ((char *) dst->data + i1*nb1 + i02*nb2 + i03*nb3), nc);
+ }
} else {
GGML_ABORT("src0->type = %d (%s) not supported", src0->type, ggml_type_name(src0->type));
}
} break;
case GGML_TYPE_F16:
{
- if (dst->type == GGML_TYPE_F16) {
- if (src1->type == GGML_TYPE_I64) {
- ggml_compute_forward_set_rows_impl<ggml_fp16_t, int64_t>(params, dst);
- } else if (src1->type == GGML_TYPE_I32) {
- ggml_compute_forward_set_rows_impl<ggml_fp16_t, int32_t>(params, dst);
- } else {
- GGML_ABORT("src1->type = %d (%s) not supported", src1->type, ggml_type_name(src1->type));
- }
+ if (src1->type == GGML_TYPE_I64) {
+ ggml_compute_forward_set_rows_impl<ggml_fp16_t, int64_t>(params, dst);
+ } else if (src1->type == GGML_TYPE_I32) {
+ ggml_compute_forward_set_rows_impl<ggml_fp16_t, int32_t>(params, dst);
} else {
- GGML_ABORT("dst->type = %d (%s) not supported with src0->type = %d (%s)", dst->type, ggml_type_name(dst->type), src0->type, ggml_type_name(src0->type));
+ GGML_ABORT("src1->type = %d (%s) not supported", src1->type, ggml_type_name(src1->type));
}
} break;
default:
return op->src[0]->type != GGML_TYPE_NVFP4;
case GGML_OP_SET_ROWS:
{
- if (op->src[0]->type != GGML_TYPE_F32 && op->src[0]->type != GGML_TYPE_F16) {
+ if (op->src[0]->type == GGML_TYPE_F16) {
+ return op->type == GGML_TYPE_F16;
+ }
+
+ if (op->src[0]->type != GGML_TYPE_F32) {
return false;
}
bool uma;
bool prefer_host_memory;
bool float_controls_rte_fp16;
+ bool float_controls_denorm_preserve_fp16;
bool subgroup_basic;
bool subgroup_arithmetic;
bool subgroup_shuffle;
vk_pipeline pipeline_cpy_f32_quant[GGML_TYPE_COUNT];
vk_pipeline pipeline_cpy_quant_f32[GGML_TYPE_COUNT];
vk_pipeline pipeline_cpy_transpose_16, pipeline_cpy_transpose_32;
- vk_pipeline pipeline_set_rows_i32[GGML_TYPE_COUNT];
- vk_pipeline pipeline_set_rows_i64[GGML_TYPE_COUNT];
+ // [src0 0=fp32,1=fp16][dst]
+ vk_pipeline pipeline_set_rows_i32[2][GGML_TYPE_COUNT];
+ vk_pipeline pipeline_set_rows_i64[2][GGML_TYPE_COUNT];
vk_pipeline pipeline_norm_f32;
vk_pipeline pipeline_group_norm_f32;
vk_pipeline pipeline_rms_norm_f32;
vk::ShaderModuleCreateInfo shader_module_create_info({}, spv_size, reinterpret_cast<const uint32_t *>(spv_data));
- // Patch SPIR-V to enable RTE rounding for FP16, avoiding the need for
- // separate shader variants compiled with -DRTE16.
+ // Patch SPIR-V to enable supported FP16 float controls, avoiding the need
+ // for separate shader variants.
std::vector<uint32_t> spirv;
- if (device->float_controls_rte_fp16) {
+ if (device->float_controls_rte_fp16 || device->float_controls_denorm_preserve_fp16) {
const uint32_t* spv_words = reinterpret_cast<const uint32_t *>(spv_data);
size_t word_count = spv_size / sizeof(uint32_t);
spirv.assign(spv_words, spv_words + word_count);
// Insert from latest position first so earlier indices stay valid.
- // OpExecutionMode %entrypoint RoundingModeRTE 16
- uint32_t exec_mode[] = { (4u << spv::WordCountShift) | spv::OpExecutionMode, entry_point_id, spv::ExecutionModeRoundingModeRTE, 16 };
- spirv.insert(spirv.begin() + exec_insert_pos, std::begin(exec_mode), std::end(exec_mode));
+ if (device->float_controls_rte_fp16) {
+ // OpExecutionMode %entrypoint RoundingModeRTE 16
+ uint32_t exec_mode[] = { (4u << spv::WordCountShift) | spv::OpExecutionMode, entry_point_id, spv::ExecutionModeRoundingModeRTE, 16 };
+ spirv.insert(spirv.begin() + exec_insert_pos, std::begin(exec_mode), std::end(exec_mode));
+ }
+
+ if (device->float_controls_denorm_preserve_fp16) {
+ // OpExecutionMode %entrypoint DenormPreserve 16
+ uint32_t exec_mode[] = { (4u << spv::WordCountShift) | spv::OpExecutionMode, entry_point_id, spv::ExecutionModeDenormPreserve, 16 };
+ spirv.insert(spirv.begin() + exec_insert_pos, std::begin(exec_mode), std::end(exec_mode));
+ }
// OpExtension "SPV_KHR_float_controls"
const char ext_str[] = "SPV_KHR_float_controls";
memcpy(&extension[1], ext_str, sizeof(ext_str));
spirv.insert(spirv.begin() + ext_insert_pos, extension.begin(), extension.end());
- // OpCapability RoundingModeRTE
- uint32_t capability[] = { (2u << spv::WordCountShift) | spv::OpCapability, spv::CapabilityRoundingModeRTE };
- spirv.insert(spirv.begin() + cap_insert_pos, std::begin(capability), std::end(capability));
+ if (device->float_controls_rte_fp16) {
+ // OpCapability RoundingModeRTE
+ uint32_t capability[] = { (2u << spv::WordCountShift) | spv::OpCapability, spv::CapabilityRoundingModeRTE };
+ spirv.insert(spirv.begin() + cap_insert_pos, std::begin(capability), std::end(capability));
+ }
+
+ if (device->float_controls_denorm_preserve_fp16) {
+ // OpCapability DenormPreserve
+ uint32_t capability[] = { (2u << spv::WordCountShift) | spv::OpCapability, spv::CapabilityDenormPreserve };
+ spirv.insert(spirv.begin() + cap_insert_pos, std::begin(capability), std::end(capability));
+ }
shader_module_create_info = vk::ShaderModuleCreateInfo({}, spirv.size() * sizeof(uint32_t), spirv.data());
}
ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_len, cpy_f32_q8_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1);
ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_len, cpy_f32_iq4_nl_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1);
-#define SET_ROWS(itype) \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_F32], "set_rows_f32" #itype, set_rows_f32 ## itype ## _len, set_rows_f32 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_F16], "set_rows_f16" #itype, set_rows_f16 ## itype ## _len, set_rows_f16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_BF16], "set_rows_bf16" #itype, set_rows_bf16 ## itype ## _len, set_rows_bf16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q1_0], "set_rows_q1_0" #itype, set_rows_q1_0 ## itype ## _len, set_rows_q1_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q4_0], "set_rows_q4_0" #itype, set_rows_q4_0 ## itype ## _len, set_rows_q4_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q4_1], "set_rows_q4_1" #itype, set_rows_q4_1 ## itype ## _len, set_rows_q4_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q5_0], "set_rows_q5_0" #itype, set_rows_q5_0 ## itype ## _len, set_rows_q5_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q5_1], "set_rows_q5_1" #itype, set_rows_q5_1 ## itype ## _len, set_rows_q5_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q8_0], "set_rows_q8_0" #itype, set_rows_q8_0 ## itype ## _len, set_rows_q8_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_IQ4_NL], "set_rows_iq4_nl" #itype, set_rows_iq4_nl ## itype ## _len, set_rows_iq4_nl ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true);
-
- SET_ROWS(_i32)
- SET_ROWS(_i64)
+#define SET_ROWS(src_idx, src, itype) \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_F32], "set_rows_" #src "_f32" #itype, set_rows_ ## src ## _f32 ## itype ## _len, set_rows_ ## src ## _f32 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_F16], "set_rows_" #src "_f16" #itype, set_rows_ ## src ## _f16 ## itype ## _len, set_rows_ ## src ## _f16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_BF16], "set_rows_" #src "_bf16" #itype, set_rows_ ## src ## _bf16 ## itype ## _len, set_rows_ ## src ## _bf16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q1_0], "set_rows_" #src "_q1_0" #itype, set_rows_ ## src ## _q1_0 ## itype ## _len, set_rows_ ## src ## _q1_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q4_0], "set_rows_" #src "_q4_0" #itype, set_rows_ ## src ## _q4_0 ## itype ## _len, set_rows_ ## src ## _q4_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q4_1], "set_rows_" #src "_q4_1" #itype, set_rows_ ## src ## _q4_1 ## itype ## _len, set_rows_ ## src ## _q4_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q5_0], "set_rows_" #src "_q5_0" #itype, set_rows_ ## src ## _q5_0 ## itype ## _len, set_rows_ ## src ## _q5_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q5_1], "set_rows_" #src "_q5_1" #itype, set_rows_ ## src ## _q5_1 ## itype ## _len, set_rows_ ## src ## _q5_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q8_0], "set_rows_" #src "_q8_0" #itype, set_rows_ ## src ## _q8_0 ## itype ## _len, set_rows_ ## src ## _q8_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_IQ4_NL], "set_rows_" #src "_iq4_nl" #itype, set_rows_ ## src ## _iq4_nl ## itype ## _len, set_rows_ ## src ## _iq4_nl ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true);
+
+ SET_ROWS(0, f32, _i32)
+ SET_ROWS(0, f32, _i64)
+ SET_ROWS(1, f16, _i32)
+ SET_ROWS(1, f16, _i64)
#undef SET_ROWS
device->shader_core_count = 0;
}
device->float_controls_rte_fp16 = vk12_props.shaderRoundingModeRTEFloat16;
+ device->float_controls_denorm_preserve_fp16 = vk12_props.shaderDenormPreserveFloat16;
device->subgroup_basic = (vk11_props.subgroupSupportedStages & vk::ShaderStageFlagBits::eCompute) &&
(vk11_props.subgroupSupportedOperations & vk::SubgroupFeatureFlagBits::eBasic);
case GGML_OP_DUP:
return ggml_vk_get_cpy_pipeline(ctx, src0, dst, dst->type);
case GGML_OP_SET_ROWS:
- if (src1->type == GGML_TYPE_I64) {
- return ctx->device->pipeline_set_rows_i64[dst->type];
- } else {
- return ctx->device->pipeline_set_rows_i32[dst->type];
+ {
+ if (src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) {
+ return nullptr;
+ }
+ const int src_idx = src0->type == GGML_TYPE_F16;
+ if (src1->type == GGML_TYPE_I64) {
+ return ctx->device->pipeline_set_rows_i64[src_idx][dst->type];
+ } else if (src1->type == GGML_TYPE_I32) {
+ return ctx->device->pipeline_set_rows_i32[src_idx][dst->type];
+ }
+ return nullptr;
}
case GGML_OP_SILU_BACK:
if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
return op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32;
case GGML_OP_SET_ROWS:
{
- if (op->src[0]->type == GGML_TYPE_F32) {
- switch (op->type) {
- case GGML_TYPE_F32:
- case GGML_TYPE_F16:
- case GGML_TYPE_BF16:
- case GGML_TYPE_Q1_0:
- case GGML_TYPE_Q4_0:
- case GGML_TYPE_Q4_1:
- case GGML_TYPE_Q5_0:
- case GGML_TYPE_Q5_1:
- case GGML_TYPE_Q8_0:
- case GGML_TYPE_IQ4_NL:
- return true;
- default:
- return false;
- }
+ if ((op->src[0]->type != GGML_TYPE_F32 && op->src[0]->type != GGML_TYPE_F16) ||
+ (op->src[1]->type != GGML_TYPE_I32 && op->src[1]->type != GGML_TYPE_I64)) {
+ return false;
+ }
+ switch (op->type) {
+ case GGML_TYPE_F32:
+ case GGML_TYPE_F16:
+ case GGML_TYPE_BF16:
+ case GGML_TYPE_Q1_0:
+ case GGML_TYPE_Q4_0:
+ case GGML_TYPE_Q4_1:
+ case GGML_TYPE_Q5_0:
+ case GGML_TYPE_Q5_1:
+ case GGML_TYPE_Q8_0:
+ case GGML_TYPE_IQ4_NL:
+ return true;
+ default:
+ return false;
}
- return false;
}
case GGML_OP_CONT:
case GGML_OP_CPY:
const uint BLOCK_SIZE = 32;
#endif
-layout (binding = 0) readonly buffer S {float data_s[];};
+layout (binding = 0) readonly buffer S {S_TYPE data_s[];};
#if defined(SET_ROWS)
#include "generic_binary_head.glsl"
float vmax = 0.0;
[[unroll]] for (int j = 0; j < QUANT_K_Q4_0; ++j) {
- const float v = data_s[src_idx + j];
+ const float v = float(data_s[src_idx + j]);
if (amax < abs(v)) {
amax = abs(v);
vmax = v;
data_q[dst_idx].d = float16_t(d);
[[unroll]] for (int j = 0; j < QUANT_K_Q4_0/2; ++j) {
- const float x0 = data_s[src_idx + 0 + j]*id;
- const float x1 = data_s[src_idx + QUANT_K_Q4_0/2 + j]*id;
+ const float x0 = float(data_s[src_idx + 0 + j])*id;
+ const float x1 = float(data_s[src_idx + QUANT_K_Q4_0/2 + j])*id;
const uint xi0 = min(15, int(x0 + 8.5));
const uint xi1 = min(15, int(x1 + 8.5));
float vmax = -vmin;
[[unroll]] for (int j = 0; j < QUANT_K_Q4_1; ++j) {
- const float v = data_s[src_idx + j];
+ const float v = float(data_s[src_idx + j]);
if (v < vmin) vmin = v;
if (v > vmax) vmax = v;
data_q[dst_idx].m = float16_t(vmin);
[[unroll]] for (int j = 0; j < QUANT_K_Q4_1/2; ++j) {
- const float x0 = (data_s[src_idx + 0 + j] - vmin)*id;
- const float x1 = (data_s[src_idx + QUANT_K_Q4_1/2 + j] - vmin)*id;
+ const float x0 = (float(data_s[src_idx + 0 + j]) - vmin)*id;
+ const float x1 = (float(data_s[src_idx + QUANT_K_Q4_1/2 + j]) - vmin)*id;
const uint xi0 = min(15, int(x0 + 0.5));
const uint xi1 = min(15, int(x1 + 0.5));
float vmax = 0.0;
[[unroll]] for (int j = 0; j < QUANT_K_Q5_0; ++j) {
- const float v = data_s[src_idx + j];
+ const float v = float(data_s[src_idx + j]);
if (amax < abs(v)) {
amax = abs(v);
vmax = v;
uint32_t qh = 0;
[[unroll]] for (int j = 0; j < QUANT_K_Q5_0/2; ++j) {
- const float x0 = data_s[src_idx + 0 + j]*id;
- const float x1 = data_s[src_idx + QUANT_K_Q5_0/2 + j]*id;
+ const float x0 = float(data_s[src_idx + 0 + j])*id;
+ const float x1 = float(data_s[src_idx + QUANT_K_Q5_0/2 + j])*id;
const uint xi0 = min(31, int(x0 + 16.5));
const uint xi1 = min(31, int(x1 + 16.5));
#if defined(DATA_A_Q5_1)
void quantize(uint dst_idx, uint src_idx)
{
- float min = data_s[src_idx + 0];
+ float min = float(data_s[src_idx + 0]);
float max = min;
[[unroll]] for (int j = 1; j < QUANT_K_Q5_1; ++j) {
- const float v = data_s[src_idx + j];
+ const float v = float(data_s[src_idx + j]);
min = v < min ? v : min;
max = v > max ? v : max;
}
uint32_t qh = 0;
[[unroll]] for (int j = 0; j < QUANT_K_Q5_1/2; ++j) {
- const float x0 = (data_s[src_idx + 0 + j] - min)*id;
- const float x1 = (data_s[src_idx + QUANT_K_Q5_1/2 + j] - min)*id;
+ const float x0 = (float(data_s[src_idx + 0 + j]) - min)*id;
+ const float x1 = (float(data_s[src_idx + QUANT_K_Q5_1/2 + j]) - min)*id;
const uint xi0 = uint(x0 + 0.5);
const uint xi1 = uint(x1 + 0.5);
float amax = 0.0; // absolute max
[[unroll]] for (int j = 0; j < QUANT_K_Q8_0; j++) {
- const float v = data_s[src_idx + j];
+ const float v = float(data_s[src_idx + j]);
amax = max(amax, abs(v));
}
data_q[dst_idx].d = float16_t(d);
[[unroll]] for (int j = 0; j < QUANT_K_Q8_0; ++j) {
- const float x0 = data_s[src_idx + j]*id;
+ const float x0 = float(data_s[src_idx + j])*id;
data_q[dst_idx].qs[j] = int8_t(round(x0));
}
float sum_abs = 0.0;
[[unroll]] for (int j = 0; j < QUANT_K_Q1_0; j++) {
- sum_abs += abs(data_s[src_idx + j]);
+ sum_abs += abs(float(data_s[src_idx + j]));
}
const float d = sum_abs / QUANT_K_Q1_0;
}
[[unroll]] for (int j = 0; j < QUANT_K_Q1_0; ++j) {
- if (data_s[src_idx + j] >= 0.0) {
+ if (float(data_s[src_idx + j]) >= 0.0) {
data_q[dst_idx].qs[j / 8] |= uint8_t(1 << (j % 8));
}
}
float vmax = 0.0;
[[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL; ++j) {
- const float v = data_s[src_idx + j];
+ const float v = float(data_s[src_idx + j]);
if (amax < abs(v)) {
amax = abs(v);
vmax = v;
float sumqx = 0, sumq2 = 0;
[[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL/2; ++j) {
- const float x0 = data_s[src_idx + 0 + j]*id;
- const float x1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*id;
+ const float x0 = float(data_s[src_idx + 0 + j])*id;
+ const float x1 = float(data_s[src_idx + QUANT_K_IQ4_NL/2 + j])*id;
const uint xi0 = best_index(x0);
const uint xi1 = best_index(x1);
data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
const float v0 = kvalues_iq4nl[xi0];
const float v1 = kvalues_iq4nl[xi1];
- const float w0 = data_s[src_idx + 0 + j]*data_s[src_idx + 0 + j];
- const float w1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*data_s[src_idx + QUANT_K_IQ4_NL/2 + j];
- sumqx += w0*v0*data_s[src_idx + j] + w1*v1*data_s[src_idx + QUANT_K_IQ4_NL/2 + j];
+ const float w0 = float(data_s[src_idx + 0 + j])*float(data_s[src_idx + 0 + j]);
+ const float w1 = float(data_s[src_idx + QUANT_K_IQ4_NL/2 + j])*float(data_s[src_idx + QUANT_K_IQ4_NL/2 + j]);
+ sumqx += w0*v0*float(data_s[src_idx + j]) + w1*v1*float(data_s[src_idx + QUANT_K_IQ4_NL/2 + j]);
sumq2 += w0*v0*v0 + w1*v1*v1;
}
#if defined(DATA_A_F32) || defined(DATA_A_F16)
void quantize(uint dst_idx, uint src_idx)
{
- data_q[dst_idx] = A_TYPE(data_s[src_idx]);
+ data_q[dst_idx] = A_TYPE(float(data_s[src_idx]));
}
#endif
#if defined(DATA_A_BF16)
void quantize(uint dst_idx, uint src_idx)
{
- data_q[dst_idx] = A_TYPE(fp32_to_bf16(data_s[src_idx]));
+ data_q[dst_idx] = A_TYPE(fp32_to_bf16(float(data_s[src_idx])));
}
#endif
string_to_spv("cpy_transpose_32", "copy_transpose.comp", {{"A_TYPE", "uint"}, {"D_TYPE", "uint"}});
for (std::string t : {"q1_0", "q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) {
- string_to_spv("cpy_f32_" + t, "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
+ string_to_spv("cpy_f32_" + t, "copy_to_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"S_TYPE", "float"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
string_to_spv("cpy_" + t + "_f32", "copy_from_quant.comp", {{"DATA_A_" + to_uppercase(t), "1"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
}
- for (std::string t : {"f32", "f16", "bf16", "q1_0", "q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) {
- string_to_spv("set_rows_" + t + "_i32", "copy_to_quant.comp", {{"SET_ROWS", "1"}, {"DATA_A_" + to_uppercase(t), "1"}, {"B_TYPE", "uint"}, {"B_SIZE", "32"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
- string_to_spv("set_rows_" + t + "_i64", "copy_to_quant.comp", {{"SET_ROWS", "1"}, {"DATA_A_" + to_uppercase(t), "1"}, {"B_TYPE", "uvec2"}, {"B_SIZE", "64"}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
+ for (auto src : {std::pair{"f32", "float"}, std::pair{"f16", "float16_t"}}) {
+ for (std::string dst : {"f32", "f16", "bf16", "q1_0", "q4_0", "q4_1", "q5_0", "q5_1", "q8_0", "iq4_nl"}) {
+ string_to_spv("set_rows_" + std::string(src.first) + "_" + dst + "_i32", "copy_to_quant.comp", {{"SET_ROWS", "1"}, {"DATA_A_" + to_uppercase(dst), "1"}, {"B_TYPE", "uint"}, {"B_SIZE", "32"}, {"S_TYPE", src.second}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
+ string_to_spv("set_rows_" + std::string(src.first) + "_" + dst + "_i64", "copy_to_quant.comp", {{"SET_ROWS", "1"}, {"DATA_A_" + to_uppercase(dst), "1"}, {"B_TYPE", "uvec2"}, {"B_SIZE", "64"}, {"S_TYPE", src.second}, {"D_TYPE", "float"}, {"FLOAT_TYPE", "float"}});
+ }
}
auto get_type_str = [](bool f16) {
void initialize_tensors(ggml_context * ctx) override {
for (ggml_tensor * t = ggml_get_first_tensor(ctx); t != NULL; t = ggml_get_next_tensor(ctx, t)) {
+ if (ggml_is_view_op(t->op)) {
+ continue;
+ }
if (t->type == GGML_TYPE_I64 || t->type == GGML_TYPE_I32) {
- if (ggml_is_view_op(t->op)) {
- continue;
- }
-
init_set_rows_row_ids(t, ne[1]);
} else {
init_tensor_uniform(t);
err_estimate /= 8.0f;
}
err_estimate *= err_estimate;
+ if (type_src == GGML_TYPE_F16) {
+ err_estimate *= 16.0f;
+ }
err_estimate /= 0.25f*float(ne[0] * r * ne[2]*nr23[0] * ne[3]*nr23[1]);
return err_estimate;
}
test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, GGML_TYPE_F32, GGML_TYPE_I64, { 1, 8, 1, 3 }, { 1, 1 }, 2, false));
test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, GGML_TYPE_F32, GGML_TYPE_I32, { 1, 8, 1, 3 }, { 1, 1 }, 2, false));
test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, GGML_TYPE_Q8_0, GGML_TYPE_I32, { 256, 5, 1, 3 }, { 1, 1, }, 1, false));
- for (ggml_type type : all_types) {
- for (int b : {1, 7}) {
- for (bool v : {false, true}) {
- test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, type, GGML_TYPE_I64, { 256, 5, b, 3 }, { 1, 1, }, 1, v));
- test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, type, GGML_TYPE_I64, { 256, 11, 1, b }, { 2, 3, }, 7, v));
-
- test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, type, GGML_TYPE_I64, { 3*ggml_blck_size(type), 3, b, 1 }, { 2, 3, }, 2, v));
-
- if (ggml_blck_size(type) == 1) {
- test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, type, GGML_TYPE_I64, { 31, 3, b, 1 }, { 2, 3, }, 2, v));
- test_cases.emplace_back(new test_set_rows(GGML_TYPE_F32, type, GGML_TYPE_I64, { 33, 5, 1, b }, { 2, 3, }, 1, v));
+ for (ggml_type src_type : {GGML_TYPE_F16, GGML_TYPE_F32}) {
+ for (ggml_type type : all_types) {
+ for (int b : {1, 7}) {
+ for (bool v : {false, true}) {
+ test_cases.emplace_back(new test_set_rows(src_type, type, GGML_TYPE_I64, { 256, 5, b, 3 }, { 1, 1, }, 1, v));
+ test_cases.emplace_back(new test_set_rows(src_type, type, GGML_TYPE_I64, { 256, 11, 1, b }, { 2, 3, }, 7, v));
+
+ test_cases.emplace_back(new test_set_rows(src_type, type, GGML_TYPE_I64, { 3*ggml_blck_size(type), 3, b, 1 }, { 2, 3, }, 2, v));
+
+ if (ggml_blck_size(type) == 1) {
+ test_cases.emplace_back(new test_set_rows(src_type, type, GGML_TYPE_I64, { 31, 3, b, 1 }, { 2, 3, }, 2, v));
+ test_cases.emplace_back(new test_set_rows(src_type, type, GGML_TYPE_I64, { 33, 5, 1, b }, { 2, 3, }, 1, v));
+ }
}
}
}