Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ struct FullyConnectedImplementationManager : public ImplementationManager {
one_of(in0_dt, {data_types::f16, data_types::bf16, data_types::f32, data_types::i8, data_types::u8}) &&
one_of(wei_dt, {data_types::u8, data_types::i8, data_types::u4, data_types::i4, data_types::u3, data_types::u2}) &&
one_of(out_dt, {data_types::f16, data_types::bf16, data_types::f32, data_types::u8, data_types::i8}) &&
(wei_dt != data_types::u2 || in0_dt == data_types::f16); // u2 oneDNN kernel requires f16 activations
(wei_dt != data_types::u2 || in0_dt == data_types::f16 || // u2 needs f16 activations, except on Xe2/Xe3:
(in0_dt == data_types::i8 && one_of(info.arch, {gpu_arch::xe2, gpu_arch::xe3}))); // oneDNN has u2 x s8 kernels there
const bool fp_compressed_case = fc_prim->compressed_weights && one_of(in0_dt, {data_types::f8e4m3, data_types::f4e2m1, data_types::f8e5m2}) &&
one_of(wei_dt, {data_types::f8e4m3, data_types::f4e2m1, data_types::f8e5m2}) && one_of(out_dt, {data_types::f16, data_types::f32});
if (!f16f16_case && !bf16bf16_case && !f32f32_case && !u8s8_case && !compressed_case && !fp_compressed_case) {
Expand Down
23 changes: 20 additions & 3 deletions src/plugins/intel_gpu/src/plugin/transformations_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,10 @@ void TransformationsPipeline::apply(std::shared_ptr<ov::Model> func) {
// the whole model if a linear-attention block is detected.
const bool use_gs128_for_linear_attention = is_hybrid_linear_attention_model(*func);
const bool use_gs128_for_int8_per_token = m_context->get_engine().get_device_info().arch >= cldnn::gpu_arch::xe2;
// oneDNN has int8-activation kernels for u2 weights on Xe2 and Xe3, measured faster than f16 on both.
const auto u2_arch = m_context->get_engine().get_device_info().arch;
const bool u2_int8_activations = u2_arch == cldnn::gpu_arch::xe2 || u2_arch == cldnn::gpu_arch::xe3;
const uint64_t dynamic_quantization_threshold = config.get_dynamic_quantization_threshold();

pass_config->set_callback<ov::intel_gpu::DynamicQuantizeFullyConnected>([=](const_node_ptr& root) -> bool {
const int64_t dyn_quan_bisect = GPU_DEBUG_VALUE_OR(config.get_dynamic_quantization_bisect(), 0); // 0 will be ignored from GPU_DEBUG_IF
Expand All @@ -1909,11 +1913,24 @@ void TransformationsPipeline::apply(std::shared_ptr<ov::Model> func) {
return true;
}
}
// u2 oneDNN kernel expects fp16 activations; disabled until i8 activation support is added
if (root->get_input_element_type(1) == ov::element::u2) {
GPU_DEBUG_TRACE << root->get_friendly_name() << " dyn_quan is turned off: u2 weights require fp16 activations" << std::endl;
if (root->get_input_element_type(1) == ov::element::u2 && !u2_int8_activations) {
GPU_DEBUG_TRACE << root->get_friendly_name() << " dyn_quan is turned off: u2 int8 activations are not enabled on this device" << std::endl;
return true;
}
// Small batches are skipped at runtime (dynamic_quantization_threshold), but only for dynamic shapes:
// in a statically shaped model, e.g. a separate decode model, the activations would always be
// quantized. u2 has int8-activation kernels for prefill-sized batches only, so keep f16 there.
if (root->get_input_element_type(1) == ov::element::u2) {
const auto& act_shape = root->get_input_partial_shape(0);
if (act_shape.is_static() && act_shape.size() >= 2) {
const auto rows = ov::shape_size(act_shape.to_shape()) / act_shape.to_shape().back();
if (rows <= dynamic_quantization_threshold) {
GPU_DEBUG_TRACE << root->get_friendly_name() << " dyn_quan is turned off: static batch " << rows
<< " is below the dynamic quantization threshold" << std::endl;
return true;
}
}
}

uint64_t adj_group_size = dynamic_quantization_group_size;
const bool is_wei_i8u8 = cldnn::one_of(root->get_input_element_type(1), {ov::element::i8, ov::element::u8});
Expand Down
Loading