-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TODO List #2
Comments
llama.cpp 算子性能对比[toc] 环境信息
构建命令mkdir build
cd build
cmake .. -DLLAMA_CANN=ON
cmake --build . --config Release 算子性能对比GGML_OP_ADD 😄
GGML_OP_ACC 😄
GGML_OP_MUL 😄
GGML_OP_DIV 😄
GGML_UNARY_OP_GELU 😄
GGML_UNARY_OP_SILU 😄
GGML_UNARY_OP_GELU_QUICK 😄实际上调用的是GELU算子,未实GELU_QUICK。
GGML_UNARY_OP_TANH 😄
GGML_UNARY_OP_RELU 😄
GGML_UNARY_OP_HARDSIGMOID 😄
GGML_UNARY_OP_HARDSWISH 😄
GGML_OP_NORM 😄
GGML_OP_GROUP_NORM 😄
GGML_OP_UPSCALE ❓ (算子执行出错)
GGML_OP_PAD 😄
GGML_OP_LEAKY_RELU 😄
GGML_OP_SCALE 😄
GGML_OP_CLAMP 😄
GGML_OP_ARGSORT 😄
GGML_OP_CONCAT 🌚执行慢的原因:算子本身执行慢。
GGML_OP_REPEAT 🌚执行慢的原因:算子本身执行慢。
GGML_OP_ARANGE 🌚执行慢的原因:算子本身执行慢。
GGML_OP_TIMESTEP_EMBEDDING 🌚 (需实现融合算子)执行慢的原因:调用了多个算子组合,需要融合算子
GGML_OP_RMS_NORM 🌚(需修改算子接口)执行慢的原因:gamma是必传参数,需要构造全1矩阵,rstd输出是必传参数,需要申请设备上内存。
GGML_OP_SQR 🌚执行慢的原因:算子本身执行慢。
GGML_OP_CONT 🌚执行慢的原因:算子本身执行慢。
GGML_OP_DIAG_MASK_INF 🌚 (需实现融合算子)执行慢的原因:调用了多个算子组合,需要融合算子
GGML_OP_IM2COL 🌚 (需实现融合算子)执行慢的原因:调用了多个算子组合,需要融合算子
GGML_OP_POOL_2D 🌚 (需实现融合算子)执行慢的原因:max pool 调用了多个算子组合,需要融合算子,算子本身也慢
GGML_OP_SUM_ROWS 🌚执行慢的原因:算子本身执行慢。
GGML_OP_DUP 🌚执行慢的原因:算子本身执行慢。
GGML_OP_SOFTMAX (需实现融合算子)GGML_OP_ROPE (需实现融合算子)GGML_OP_ALIBI 🌚 (需实现融合算子)执行慢的原因:max pool 调用了多个算子组合,需要融合算子
|
量化算法需求[toc] 计划支持常用量化算法GGML_TYPE_Q4_0(最常用,ollama latest默认类型)量化分组格式 #define QK4_0 32 // 每组32个f32数据
typedef struct {
ggml_half d; // 公共系数
uint8_t qs[QK4_0 / 2]; // 4bit存储的数据
} block_q4_0; 量化算法描述 void quantize_row_q4_0_reference(const float * restrict x, block_q4_0 * restrict y, int64_t k) {
static const int qk = QK4_0;
assert(k % qk == 0);
const int nb = k / qk;
// 1. 找到绝对值最大的数的值
for (int i = 0; i < nb; i++) {
float amax = 0.0f; // absolute max
float max = 0.0f;
for (int j = 0; j < qk; j++) {
const float v = x[i*qk + j];
if (amax < fabsf(v)) {
amax = fabsf(v);
max = v;
}
}
// 2. 公共系数是第一步的值除以 -8
const float d = max / -8;
const float id = d ? 1.0f/d : 0.0f;
y[i].d = GGML_FP32_TO_FP16(d);
// 3. 对组内的所有数据,除以公共系数,然后按以下顺序存储
// 量化前: 1,2,3,4,5,6,7,8 ...... 30,31
// 量化后: 1,16,2,17,3,18 ...... 15,31
// 也就是数据按顺序先填充量化后组的低4位,然后再填充高4位。
for (int j = 0; j < qk/2; ++j) {
const float x0 = x[i*qk + 0 + j]*id;
const float x1 = x[i*qk + qk/2 + j]*id;
// 量化的值+8.5,溢出后取最大值。
const uint8_t xi0 = MIN(15, (int8_t)(x0 + 8.5f));
const uint8_t xi1 = MIN(15, (int8_t)(x1 + 8.5f));
y[i].qs[j] = xi0;
y[i].qs[j] |= xi1 << 4;
}
}
} 反量化算法描述 void dequantize_row_q4_0(const block_q4_0 * restrict x, float * restrict y, int64_t k) {
static const int qk = QK4_0;
assert(k % qk == 0);
const int nb = k / qk;
for (int i = 0; i < nb; i++) {
const float d = GGML_FP16_TO_FP32(x[i].d);
// 1. 量化后的4bit数据-8
for (int j = 0; j < qk/2; ++j) {
const int x0 = (x[i].qs[j] & 0x0F) - 8;
const int x1 = (x[i].qs[j] >> 4) - 8;
// 2. 数据乘以公共系数后按以下顺序存储:
// 反量化前: 1,16,2,17,3,18 ...... 15,31
// 反量化后: 1,2,3,4,5,6,7,8 ...... 30,31
y[i*qk + j + 0 ] = x0*d;
y[i*qk + j + qk/2] = x1*d;
}
}
} GGML_TYPE_Q4_1(实现方式相似,可一同实现,下同)量化分组格式 #define QK4_1 32
typedef struct {
union {
struct {
ggml_half d; // 公共系数
ggml_half m; // 公共偏移
} GGML_COMMON_AGGR;
ggml_half2 dm;
};
uint8_t qs[QK4_1 / 2]; GGML_TYPE_Q5_0量化分组格式 #define QK5_0 32
typedef struct {
ggml_half d; // 公共系数
uint8_t qh[4]; // 5-th bit of quants
uint8_t qs[QK5_0 / 2];
} block_q5_0; 量化算法和反量化算法与Q4_0基本一致,额外记录了每个数据的第五个bit位的值,在反量化的时候恢复。 GGML_TYPE_Q5_1量化分组格式 #define QK5_1 32
typedef struct {
union {
struct {
ggml_half d; // delta
ggml_half m; // min
} GGML_COMMON_AGGR;
ggml_half2 dm;
};
uint8_t qh[4]; // 5-th bit of quants
uint8_t qs[QK5_1 / 2]; // nibbles / quants
} block_q5_1; GGML_TYPE_Q8_0#define QK8_0 32
typedef struct {
ggml_half d; // delta
int8_t qs[QK8_0];
} block_q8_0; 量化算法和反量化算法与Q4_0基本一致,区别是q8_0使用8位记录一个数据 Ascend实现难点
带量化的融合算子GGML_OP_MUL_MAT (核心算子,性能对整个推理影响非常大)输入2个矩阵(src0:量化后的tensor, src1:f32或f16),量化后的数据直接相乘,结果是float类型。 GGML_OP_MUL_MAT_ID支持多个Moe专家一起计算,计算方法与GGML_OP_MUL_MAT类似。 GGML_OP_GET_ROWS该算子实际上做了Embedding操作,但是允许输入的tensor是量化的tensor。输出F32的tensor。 GGML_OP_CPYTensor拷贝,允许从F16或者F32的tensor拷贝到一个量化的tensor中。 |
aclnn只能适配部分场景的算子: 算法有差异的算子: 不支持的算子 TOP: MUl_MAT |
excellent work! hope to get access and try it myself soon! |
The text was updated successfully, but these errors were encountered: