Skip to content
Merged
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
12 changes: 12 additions & 0 deletions ggml/src/ggml-sycl/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,10 @@ to_fp16_sycl_t ggml_get_to_fp16_sycl(ggml_type type, ggml_tensor * dst) {
switch (type) {
case GGML_TYPE_Q1_0:
return dequantize_block_sycl<QK1_0, QR1_0, dequantize_q1_0>;
case GGML_TYPE_PTQ1_0:
return dequantize_block_sycl<QK_PTQ1_0, QR_PTQ1_0, dequantize_ptq1_0>;
case GGML_TYPE_PQ2_0:
return dequantize_block_sycl<QK_PQ2_0, QR_PQ2_0, dequantize_pq2_0>;
case GGML_TYPE_Q2_0:
return dequantize_block_sycl<QK2_0, QR2_0, dequantize_q2_0>;
case GGML_TYPE_Q4_0:
Expand Down Expand Up @@ -747,6 +751,10 @@ to_fp32_sycl_t ggml_get_to_fp32_sycl(ggml_type type, ggml_tensor *dst) {
switch (type) {
case GGML_TYPE_Q1_0:
return dequantize_block_sycl<QK1_0, QR1_0, dequantize_q1_0>;
case GGML_TYPE_PTQ1_0:
return dequantize_block_sycl<QK_PTQ1_0, QR_PTQ1_0, dequantize_ptq1_0>;
case GGML_TYPE_PQ2_0:
return dequantize_block_sycl<QK_PQ2_0, QR_PQ2_0, dequantize_pq2_0>;
case GGML_TYPE_Q2_0:
return dequantize_block_sycl<QK2_0, QR2_0, dequantize_q2_0>;
case GGML_TYPE_Q4_0:
Expand Down Expand Up @@ -861,6 +869,10 @@ to_fp16_nc_sycl_t ggml_get_to_fp16_nc_sycl(ggml_type type) {
#endif
case GGML_TYPE_Q1_0:
return dequantize_block_nc_sycl<QK1_0, QR1_0, dequantize_q1_0>;
case GGML_TYPE_PTQ1_0:
return dequantize_block_nc_sycl<QK_PTQ1_0, QR_PTQ1_0, dequantize_ptq1_0>;
case GGML_TYPE_PQ2_0:
return dequantize_block_nc_sycl<QK_PQ2_0, QR_PQ2_0, dequantize_pq2_0>;
case GGML_TYPE_Q4_0:
return dequantize_block_nc_sycl<QK4_0, QR4_0, dequantize_q4_0>;
case GGML_TYPE_Q4_1:
Expand Down
32 changes: 32 additions & 0 deletions ggml/src/ggml-sycl/cpy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ static void ggml_cpy_f16_q5_0_sycl(const char * cx, char * cdst, const int ne, c
static bool ggml_sycl_is_quantized_type(enum ggml_type type) {
switch (type) {
case GGML_TYPE_Q1_0:
case GGML_TYPE_PTQ1_0:
case GGML_TYPE_PQ2_0:
case GGML_TYPE_Q2_0:
case GGML_TYPE_Q4_0:
case GGML_TYPE_Q4_1:
Expand Down Expand Up @@ -955,6 +957,32 @@ static void ggml_cpy_q1_0_q1_0(const char * cx, char * cdst, const int ne, const
});
}

static void ggml_cpy_ptq1_0_ptq1_0(const char * cx, char * cdst, const int ne, const int ne00, const int ne01,
const int ne02, const int nb00, const int nb01, const int nb02, const int nb03,
const int ne10, const int ne11, const int ne12, const int nb10, const int nb11,
const int nb12, const int nb13, queue_ptr stream) {
GGML_ASSERT(ne % QK_PTQ1_0 == 0);
const int num_blocks = ceil_div(ne / QK_PTQ1_0, SYCL_CPY_BLOCK_SIZE);
stream->parallel_for(
sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
[=](sycl::nd_item<3> item_ct1) [[sycl::reqd_sub_group_size(WARP_SIZE)]] {
cpy_q_q<block_ptq1_0, QK_PTQ1_0>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1);
});
}

static void ggml_cpy_pq2_0_pq2_0(const char * cx, char * cdst, const int ne, const int ne00, const int ne01,
const int ne02, const int nb00, const int nb01, const int nb02, const int nb03,
const int ne10, const int ne11, const int ne12, const int nb10, const int nb11,
const int nb12, const int nb13, queue_ptr stream) {
GGML_ASSERT(ne % QK_PQ2_0 == 0);
const int num_blocks = ceil_div(ne / QK_PQ2_0, SYCL_CPY_BLOCK_SIZE);
stream->parallel_for(
sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) * sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE), sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
[=](sycl::nd_item<3> item_ct1) [[sycl::reqd_sub_group_size(WARP_SIZE)]] {
cpy_q_q<block_pq2_0, QK_PQ2_0>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, item_ct1);
});
}

static void ggml_cpy_q2_0_q2_0(const char * cx, char * cdst, const int ne, const int ne00, const int ne01,
const int ne02, const int nb00, const int nb01, const int nb02, const int nb03,
const int ne10, const int ne11, const int ne12, const int nb10, const int nb11,
Expand Down Expand Up @@ -1366,6 +1394,10 @@ void ggml_sycl_cpy(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, co
ggml_cpy_q4_1_q4_1(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
} else if (src0->type == GGML_TYPE_Q1_0 && src1->type == GGML_TYPE_Q1_0) {
ggml_cpy_q1_0_q1_0(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
} else if (src0->type == GGML_TYPE_PTQ1_0 && src1->type == GGML_TYPE_PTQ1_0) {
ggml_cpy_ptq1_0_ptq1_0(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
} else if (src0->type == GGML_TYPE_PQ2_0 && src1->type == GGML_TYPE_PQ2_0) {
ggml_cpy_pq2_0_pq2_0(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
} else if (src0->type == GGML_TYPE_Q2_0 && src1->type == GGML_TYPE_Q2_0) {
ggml_cpy_q2_0_q2_0(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
} else if (src0->type == GGML_TYPE_MXFP4 && src1->type == GGML_TYPE_MXFP4) {
Expand Down
53 changes: 53 additions & 0 deletions ggml/src/ggml-sycl/dequantize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,59 @@ static __dpct_inline__ void dequantize_q1_0(const void *vx, const int64_t ib,
v.y() = (2 * bit_1 - 1) * d;
}

static __dpct_inline__ int ptq1_0_trit(const block_ptq1_0 * x, const int e) {
uint8_t b;
int n;
if (e < 80) {
b = x->qs[e & 15];
n = e >> 4;
} else if (e < 120) {
const int t = e - 80;
b = x->qs[16 + (t & 7)];
n = t >> 3;
} else {
const int t = e - 120;
b = x->qh[t & 1];
n = t >> 1;
}

uint32_t v = b;
#pragma unroll
for (int i = 0; i < 4; ++i) {
if (i < n) {
v = (v * 3) & 0xFF;
}
}
return (int) ((v * 3) >> 8) - 1;
}

static __dpct_inline__ void dequantize_ptq1_0(const void * vx, const int64_t ib,
const int iqs, dfloat2 & v) {
const block_ptq1_0 * x = (const block_ptq1_0 *) vx;
const dfloat d = x[ib].d;

v.x() = ptq1_0_trit(&x[ib], iqs + 0) * d;
v.y() = ptq1_0_trit(&x[ib], iqs + 1) * d;
}

static __dpct_inline__ void dequantize_pq2_0(const void * vx, const int64_t ib,
const int iqs, dfloat2 & v) {
const block_pq2_0 * x = (const block_pq2_0 *) vx;
const dfloat d = x[ib].d;

const int byte_index_0 = iqs / 4;
const int bit_offset_0 = (iqs % 4) * 2;

const int byte_index_1 = (iqs + 1) / 4;
const int bit_offset_1 = ((iqs + 1) % 4) * 2;

const int c0 = (x[ib].qs[byte_index_0] >> bit_offset_0) & 0x3;
const int c1 = (x[ib].qs[byte_index_1] >> bit_offset_1) & 0x3;

v.x() = (c0 - 1) * d;
v.y() = (c1 - 1) * d;
}

static __dpct_inline__ void dequantize_q4_1(const void *vx, const int64_t ib,
const int iqs, dfloat2 &v) {
const block_q4_1 * x = (const block_q4_1 *) vx;
Expand Down
8 changes: 8 additions & 0 deletions ggml/src/ggml-sycl/getrows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,14 @@ void ggml_sycl_op_get_rows(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
get_rows_sycl<QK1_0, 1, dequantize_q1_0>(ctx, dst->src[0], dst->src[1], dst, (const float *)dst->src[0]->data,
src1_i32, (float *)dst->data, ctx.stream());
break;
case GGML_TYPE_PTQ1_0:
get_rows_sycl<QK_PTQ1_0, 1, dequantize_ptq1_0>(ctx, dst->src[0], dst->src[1], dst, (const float *)dst->src[0]->data,
src1_i32, (float *)dst->data, ctx.stream());
break;
case GGML_TYPE_PQ2_0:
get_rows_sycl<QK_PQ2_0, 1, dequantize_pq2_0>(ctx, dst->src[0], dst->src[1], dst, (const float *)dst->src[0]->data,
src1_i32, (float *)dst->data, ctx.stream());
break;
case GGML_TYPE_MXFP4:
get_rows_sycl<QK_MXFP4, 2, dequantize_mxfp4>(ctx, dst->src[0], dst->src[1], dst, (const float *)dst->src[0]->data,
src1_i32, (float *)dst->data, ctx.stream());
Expand Down
60 changes: 59 additions & 1 deletion ggml/src/ggml-sycl/ggml-sycl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,8 @@ static int64_t get_row_rounding(ggml_type type, const std::array<float, GGML_SYC

switch(type) {
case GGML_TYPE_Q1_0:
case GGML_TYPE_PTQ1_0:
case GGML_TYPE_PQ2_0:
case GGML_TYPE_Q4_0:
case GGML_TYPE_Q4_1:
return max_compute_capability >= VER_GEN9 ? 128 : 64;
Expand Down Expand Up @@ -3846,6 +3848,39 @@ static bool ggml_sycl_supports_dmmv(enum ggml_type type) {
}
}

static bool ggml_sycl_supports_mmvq(enum ggml_type type) {
switch (type) {
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_Q1_0:
case GGML_TYPE_PTQ1_0:
case GGML_TYPE_PQ2_0:
case GGML_TYPE_Q2_0:
case GGML_TYPE_Q2_K:
case GGML_TYPE_Q3_K:
case GGML_TYPE_Q4_K:
case GGML_TYPE_Q5_K:
case GGML_TYPE_Q6_K:
case GGML_TYPE_IQ1_S:
case GGML_TYPE_IQ1_M:
case GGML_TYPE_IQ2_XXS:
case GGML_TYPE_IQ2_XS:
case GGML_TYPE_IQ2_S:
case GGML_TYPE_IQ3_XXS:
case GGML_TYPE_IQ3_S:
case GGML_TYPE_IQ4_NL:
case GGML_TYPE_IQ4_XS:
case GGML_TYPE_MXFP4:
case GGML_TYPE_NVFP4:
return true;
default:
return false;
}
}

// Helper functions to unify device memory allocation for both async and sync paths
static inline void * sycl_ext_malloc_device(dpct::queue_ptr stream, size_t size) {
bool use_async = g_ggml_sycl_use_async_mem_op;
Expand Down Expand Up @@ -4485,7 +4520,8 @@ static bool can_use_dequantize_mul_mat_vec(const ggml_tensor * src0, const ggml_
}

static bool can_use_mul_mat_vec_q(const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
return ggml_is_quantized(src0->type) && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32 &&
return ggml_sycl_supports_mmvq(src0->type) &&
src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32 &&
src1->ne[1] <= MMVQ_MAX_BATCH_SIZE;
}

Expand Down Expand Up @@ -6018,6 +6054,14 @@ static bool do_ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, cons
a->ne[0] > 128 && a->ne[2] == 1 && src0_type == GGML_TYPE_F16) {
return false;
}

if (ggml_is_quantized(src0_type) &&
!ggml_sycl_supports_mmvq(src0_type) &&
!ggml_sycl_supports_dmmv(src0_type) &&
!ggml_sycl_supports_mmq(src0_type)) {
return false;
}

return true;
}
case GGML_OP_OUT_PROD:
Expand All @@ -6034,6 +6078,8 @@ static bool do_ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, cons
case GGML_TYPE_BF16:
case GGML_TYPE_F32:
case GGML_TYPE_Q1_0:
case GGML_TYPE_PTQ1_0:
case GGML_TYPE_PQ2_0:
case GGML_TYPE_MXFP4:
case GGML_TYPE_NVFP4:
case GGML_TYPE_IQ2_XXS:
Expand Down Expand Up @@ -6100,6 +6146,16 @@ static bool do_ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, cons
ggml_type src0_type = op->src[0]->type;
ggml_type src1_type = op->src[1]->type;

// Quantizing a float row into PTQ1_0 or PQ2_0 has no kernel: both are
// produced offline by the converter, which also applies the Hadamard
// rotation the packing assumes. ggml_sycl_cpy() would take the
// float -> quantized branch and assert, so decline the pair here and let
// the scheduler fall back. The quant -> same-quant copies are handled.
if ((src1_type == GGML_TYPE_PTQ1_0 || src1_type == GGML_TYPE_PQ2_0) &&
src0_type != src1_type) {
return false;
}

if (src0_type == GGML_TYPE_F16) {
if (src1_type == GGML_TYPE_Q2_K ||
src1_type == GGML_TYPE_Q3_K ||
Expand Down Expand Up @@ -6159,6 +6215,8 @@ static bool do_ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, cons

if (src1_type == GGML_TYPE_F32) {
if (src0_type == GGML_TYPE_Q1_0 ||
src0_type == GGML_TYPE_PTQ1_0 ||
src0_type == GGML_TYPE_PQ2_0 ||
src0_type == GGML_TYPE_NVFP4 ||
src0_type == GGML_TYPE_Q2_K ||
src0_type == GGML_TYPE_Q3_K ||
Expand Down
Loading