Various experiments, including 5-bit qunatization
This commit is contained in:
parent
6bfb00a53b
commit
29b83e5fd6
3 changed files with 211 additions and 14 deletions
|
@ -306,13 +306,17 @@ int main(int argc, char ** argv) {
|
||||||
std::vector<float> output_scratch(SCRATCH_ELEMENTS);
|
std::vector<float> output_scratch(SCRATCH_ELEMENTS);
|
||||||
|
|
||||||
// loop throught quantization types
|
// loop throught quantization types
|
||||||
for (int i = 0; i < GGML_TYPE_COUNT; i++) {
|
//for (int i = 0; i < GGML_TYPE_COUNT; i++) {
|
||||||
|
for (int i = 1; i < 2; i++) {
|
||||||
if (!params.include_types.empty() && std::find(params.include_types.begin(), params.include_types.end(), i) == params.include_types.end()) {
|
if (!params.include_types.empty() && std::find(params.include_types.begin(), params.include_types.end(), i) == params.include_types.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
quantize_fns_t qfns = ggml_internal_get_quantize_fn(i);
|
quantize_fns_t qfns = ggml_internal_get_quantize_fn(i);
|
||||||
if (i < 2 && checkNewQuantization) {
|
if (i < 2 && checkNewQuantization) {
|
||||||
qfns.quantize_row_q = i == 0 ? kQuantizeQ4_0 : kQuantizeQ4_1;
|
//qfns.quantize_row_q = i == 0 ? kQuantizeQ4_0 : kQuantizeQ4_1;
|
||||||
|
//qfns.quantize_row_q = i == 0 ? kQuantizeQ4_0 : kQuantizeQ5_1;
|
||||||
|
qfns.quantize_row_q = i == 0 ? kQuantizeQ4_0 : kQuantizeQ5_1_Fast;
|
||||||
|
if (i == 1) qfns.dequantize_row_q = kDequantizeQ5_1;
|
||||||
}
|
}
|
||||||
if (qfns.quantize_row_q && qfns.dequantize_row_q) {
|
if (qfns.quantize_row_q && qfns.dequantize_row_q) {
|
||||||
if (params.verbose) {
|
if (params.verbose) {
|
||||||
|
|
209
ggml_extra.cpp
209
ggml_extra.cpp
|
@ -1,4 +1,5 @@
|
||||||
#include "ggml_extra.h"
|
#include "ggml_extra.h"
|
||||||
|
#include "ggml.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -27,8 +28,7 @@ inline int toNearestInt(float fval) {
|
||||||
// Adapted from PR #835, function quantize_row_q4_0_rmse()
|
// Adapted from PR #835, function quantize_row_q4_0_rmse()
|
||||||
//
|
//
|
||||||
// I absolutely cannot reproduce the rmse = 0.00185915 reported in #835.
|
// I absolutely cannot reproduce the rmse = 0.00185915 reported in #835.
|
||||||
// Instead, I get rmse = 0.00197 with the original and rmse = 0.00192
|
// Instead, I get rmse = 0.00197 with the original and rmse = 0.00192 // with the modification that determines the scale actually minimizing
|
||||||
// with the modification that determines the scale actually minimizing
|
|
||||||
// the rmse.
|
// the rmse.
|
||||||
//
|
//
|
||||||
// Do I have a bug? iI don't see it.
|
// Do I have a bug? iI don't see it.
|
||||||
|
@ -79,12 +79,58 @@ float quanizeRmse(int n, const float* X, int8_t* L) {
|
||||||
//return 1/bestScale;
|
//return 1/bestScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float quanizeRmseK(int n, const float* X, int8_t* L,
|
||||||
|
int nCandidates, const float* candidates, int nmin, int nmax) {
|
||||||
|
float max = 0;
|
||||||
|
for (int i=0; i<n; ++i) max = std::max(max, std::abs(X[i]));
|
||||||
|
if (!max) { // all zero
|
||||||
|
for (int i=0; i<n; ++i) L[i] = 0;
|
||||||
|
return 1.f;
|
||||||
|
}
|
||||||
|
float best = 0, bestScale = 0;
|
||||||
|
for (int si=0; si<nCandidates; ++si) {
|
||||||
|
float iscale = candidates[si]/max;
|
||||||
|
float sumlx = 0; int suml2 = 0;
|
||||||
|
for (int i=0; i<n; ++i) {
|
||||||
|
int l = std::max(nmin, std::min(nmax, toNearestInt(iscale*X[i])));
|
||||||
|
sumlx += X[i]*l; suml2 += l*l;
|
||||||
|
}
|
||||||
|
if (sumlx*sumlx > best*suml2) {
|
||||||
|
best = sumlx*sumlx/suml2; bestScale = iscale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float sumlx = 0; int suml2 = 0;
|
||||||
|
for (int i=0; i<n; ++i) {
|
||||||
|
int l = std::max(nmin, std::min(nmax, toNearestInt(bestScale*X[i])));
|
||||||
|
sumlx += X[i]*l; suml2 += l*l;
|
||||||
|
L[i] = l;
|
||||||
|
}
|
||||||
|
return sumlx/suml2;
|
||||||
|
}
|
||||||
// The following improves the above.
|
// The following improves the above.
|
||||||
// It gives RMSE = 0.00185228 for the 7B model.
|
// It gives RMSE = 0.00185228 for the 7B model.
|
||||||
float quanizeRmseK(int n, const float* X, int8_t* L) {
|
float quanizeRmseK7(int n, const float* X, int8_t* L) {
|
||||||
constexpr int kCandiateCount = 20;
|
constexpr int kCandiateCount = 20;
|
||||||
static const float candidates[kCandiateCount] = { -8.7f, -8.5f, -8.3f, -8.1f, -7.9f, -7.7f, -7.2f, -7.0f, -6.3f, -5.7f,
|
static const float candidates[kCandiateCount] = { -8.7f, -8.5f, -8.3f, -8.1f, -7.9f, -7.7f, -7.2f, -7.0f, -6.3f, -5.7f,
|
||||||
+8.7f, +8.5f, +8.3f, +8.1f, +7.9f, +7.7f, +7.2f, +7.0f, +6.3f, +5.7f};
|
+8.7f, +8.5f, +8.3f, +8.1f, +7.9f, +7.7f, +7.2f, +7.0f, +6.3f, +5.7f};
|
||||||
|
return quanizeRmseK(n, X, L, kCandiateCount, candidates, -8, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
float quanizeRmseK15(int n, const float* X, int8_t* L) {
|
||||||
|
constexpr int kCandiateCount = 16;
|
||||||
|
static const float candidates[kCandiateCount] = {
|
||||||
|
+17.75f, +17.25f, +16.75f, +16.25f, +15.75f, +15.25f, +14.75f, +14.25f, +13.75f, +13.25f, +12.75f, +12.25, +11.75f,
|
||||||
|
+11.25f, +10.75f, +10.25f
|
||||||
|
};
|
||||||
|
return quanizeRmseK(n, X, L, kCandiateCount, candidates, 0, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast (as much faster than doing the optimization), but not very good.
|
||||||
|
float quanizeRmseFast(int n, const float* X, int8_t* L) {
|
||||||
|
//constexpr int kCandiateCount = 3;
|
||||||
|
//static const float candidates[kCandiateCount] = { +8.3f, +7.2f, +5.7f};
|
||||||
|
constexpr int kCandiateCount = 4;
|
||||||
|
static const float candidates[kCandiateCount] = { +8.7f, +7.9f, +7.2f, +5.7f};
|
||||||
float max = 0;
|
float max = 0;
|
||||||
for (int i=0; i<n; ++i) max = std::max(max, std::abs(X[i]));
|
for (int i=0; i<n; ++i) max = std::max(max, std::abs(X[i]));
|
||||||
if (!max) { // all zero
|
if (!max) { // all zero
|
||||||
|
@ -94,16 +140,62 @@ float quanizeRmseK(int n, const float* X, int8_t* L) {
|
||||||
float best = 0, bestScale = 0;
|
float best = 0, bestScale = 0;
|
||||||
for (int si=0; si<kCandiateCount; ++si) {
|
for (int si=0; si<kCandiateCount; ++si) {
|
||||||
float iscale = candidates[si]/max;
|
float iscale = candidates[si]/max;
|
||||||
|
float sumxlp = 0, sumxlm = 0;
|
||||||
|
int suml2p = 0, suml2m = 0;
|
||||||
|
for (int i=0; i<n; ++i) {
|
||||||
|
float x = X[i];
|
||||||
|
float sx = iscale*x;
|
||||||
|
int lx = toNearestInt(sx);
|
||||||
|
int lp = std::max(-8, std::min(7, +lx));
|
||||||
|
int lm = std::max(-8, std::min(7, -lx));
|
||||||
|
sumxlp += x*lp; sumxlm += x*lm;
|
||||||
|
suml2p += lp*lp; suml2m += lm*lm;
|
||||||
|
}
|
||||||
|
if (sumxlp*sumxlp*suml2m >= sumxlm*sumxlm*suml2p) {
|
||||||
|
if (sumxlp*sumxlp > best*suml2p) {
|
||||||
|
best = sumxlp*sumxlp/suml2p; bestScale = iscale;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sumxlm*sumxlm > best*suml2m) {
|
||||||
|
best = sumxlm*sumxlm/suml2m; bestScale = -iscale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
float sumlx = 0; int suml2 = 0;
|
float sumlx = 0; int suml2 = 0;
|
||||||
for (int i=0; i<n; ++i) {
|
for (int i=0; i<n; ++i) {
|
||||||
int l = std::max(-8, std::min(7, toNearestInt(iscale*X[i])));
|
int l = std::max(-8, std::min(7, toNearestInt(bestScale*X[i])));
|
||||||
sumlx += X[i]*l; suml2 += l*l;
|
sumlx += X[i]*l; suml2 += l*l;
|
||||||
|
L[i] = l;
|
||||||
}
|
}
|
||||||
if (sumlx*sumlx > best*suml2) {
|
return sumlx/suml2;
|
||||||
best = sumlx*sumlx/suml2; bestScale = iscale;
|
}
|
||||||
|
|
||||||
|
float quanizeRmseOpt(int n, const float* X, int8_t* L, std::vector<std::pair<float,int>>& work) {
|
||||||
|
work.clear();
|
||||||
|
work.reserve(n*17);
|
||||||
|
for (int l=-8; l<=8; ++l) {
|
||||||
|
float scale = l - 0.4999f;
|
||||||
|
for (int i=0; i<n; ++i) {
|
||||||
|
if (X[i]) work.push_back({scale/std::abs(X[i]), i});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float sumlx = 0; int suml2 = 0;
|
for (int i=0; i<n; ++i) L[i] = 0;
|
||||||
|
if (work.empty()) return 1.f; // all values are zero
|
||||||
|
std::sort(work.begin(), work.end());
|
||||||
|
float best = 0, bestScale = 0, lasts = work.front().first - 1;
|
||||||
|
double sumlx = 0; int suml2 = 0;
|
||||||
|
for (int k=0; k<int(work.size()); ++k) {
|
||||||
|
float s = work[k].first; int i = work[k].second;
|
||||||
|
int l = std::max(-8, std::min(7, toNearestInt(s*X[i])));
|
||||||
|
if (l != L[i]) {
|
||||||
|
sumlx += X[i]*(l-L[i]); suml2 += l*l - L[i]*L[i];
|
||||||
|
L[i] = l;
|
||||||
|
if ((s != lasts || k == int(work.size())-1) && suml2 > 0 && sumlx*sumlx > best*suml2) {
|
||||||
|
best = sumlx*sumlx/suml2; bestScale = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sumlx = 0; suml2 = 0;
|
||||||
for (int i=0; i<n; ++i) {
|
for (int i=0; i<n; ++i) {
|
||||||
int l = std::max(-8, std::min(7, toNearestInt(bestScale*X[i])));
|
int l = std::max(-8, std::min(7, toNearestInt(bestScale*X[i])));
|
||||||
sumlx += X[i]*l; suml2 += l*l;
|
sumlx += X[i]*l; suml2 += l*l;
|
||||||
|
@ -200,9 +292,10 @@ std::pair<float, float> kQuantize1(int n, const float* X, int8_t* L, std::vector
|
||||||
return {min, 1.f};
|
return {min, 1.f};
|
||||||
}
|
}
|
||||||
if (int(tmpX.size()) < n) tmpX.resize(n);
|
if (int(tmpX.size()) < n) tmpX.resize(n);
|
||||||
double a = min, b;
|
double a = min, b = 0;
|
||||||
for (int itry=0; itry<3; ++itry) {
|
for (int itry=0; itry<5; ++itry) {
|
||||||
for (int i=0; i<n; ++i) tmpX[i] = X[i] - a;
|
for (int i=0; i<n; ++i) tmpX[i] = X[i] - a;
|
||||||
|
//quanizeRmseK15(n, tmpX.data(), L);
|
||||||
kQuantize0(n, tmpX.data(), L, work, 0, 2*nmax+1);
|
kQuantize0(n, tmpX.data(), L, work, 0, 2*nmax+1);
|
||||||
double sumlx = 0, sumx = 0;
|
double sumlx = 0, sumx = 0;
|
||||||
int suml2 = 0, suml = 0;
|
int suml2 = 0, suml = 0;
|
||||||
|
@ -214,19 +307,49 @@ std::pair<float, float> kQuantize1(int n, const float* X, int8_t* L, std::vector
|
||||||
sumx += X[i];
|
sumx += X[i];
|
||||||
}
|
}
|
||||||
int64_t D = suml2*n - suml*suml;
|
int64_t D = suml2*n - suml*suml;
|
||||||
|
auto aold = a, bold = b;
|
||||||
a = (sumx*suml2 - sumlx*suml)/D;
|
a = (sumx*suml2 - sumlx*suml)/D;
|
||||||
b = (sumlx*n - sumx*suml)/D;
|
b = (sumlx*n - sumx*suml)/D;
|
||||||
|
if (itry > 0 && std::abs(a - aold) < 1e-6*std::abs(aold) && std::abs(b - bold) < 1e-6*std::abs(bold)) break;
|
||||||
}
|
}
|
||||||
return {a, b};
|
return {a, b};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<float, float> kQuantize1Fast(int n, const float* X, int8_t* L, int nmax) {
|
||||||
|
float min = X[0], max = X[1];
|
||||||
|
for (int i=1; i<n; ++i) {
|
||||||
|
min = std::min(min, X[i]); max = std::max(max, X[i]);
|
||||||
|
}
|
||||||
|
if (max == min) {
|
||||||
|
for (int i=0; i<n; ++i) L[i] = 0;
|
||||||
|
return {min, 1.f};
|
||||||
|
}
|
||||||
|
float scale = (nmax - 0.499f)/(max - min);
|
||||||
|
double sumlx = 0, sumx = 0;
|
||||||
|
int suml2 = 0, suml = 0;
|
||||||
|
for (int i=0; i<n; ++i) {
|
||||||
|
int l = toNearestInt(scale*(X[i] - min));
|
||||||
|
L[i] = l;
|
||||||
|
sumlx += X[i]*l;
|
||||||
|
suml2 += l*l;
|
||||||
|
suml += l;
|
||||||
|
sumx += X[i];
|
||||||
|
}
|
||||||
|
int64_t D = suml2*n - suml*suml;
|
||||||
|
double a = (sumx*suml2 - sumlx*suml)/D;
|
||||||
|
double b = (sumlx*n - sumx*suml)/D;
|
||||||
|
return {a, b};
|
||||||
|
}
|
||||||
|
|
||||||
void kQuantizeQ4(const float* X, void* buffer, int k, int type) {
|
void kQuantizeQ4(const float* X, void* buffer, int k, int type) {
|
||||||
assert(k % QK == 0);
|
assert(k % QK == 0);
|
||||||
|
|
||||||
auto processOne = [type] (const float* X, int8_t* L, char* y, std::vector<std::pair<float, int>>& work, std::vector<float>& tmpX) {
|
auto processOne = [type] (const float* X, int8_t* L, char* y, std::vector<std::pair<float, int>>& work, std::vector<float>& tmpX) {
|
||||||
auto q = (uint8_t*)y;
|
auto q = (uint8_t*)y;
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
auto scale = quanizeRmseK(QK, X, L);
|
auto scale = quanizeRmseK7(QK, X, L);
|
||||||
|
//auto scale = quanizeRmseFast(QK, X, L);
|
||||||
|
//auto scale = quanizeRmseOpt(QK, X, L, work);
|
||||||
// The following is not quite as good as quanizeRmseK() and it is slower too.
|
// The following is not quite as good as quanizeRmseK() and it is slower too.
|
||||||
//if (int(tmpX.size()) < QK) tmpX.resize(QK);
|
//if (int(tmpX.size()) < QK) tmpX.resize(QK);
|
||||||
//auto r1 = kQuantize0(QK, X, L, work, -8, 7);
|
//auto r1 = kQuantize0(QK, X, L, work, -8, 7);
|
||||||
|
@ -241,11 +364,29 @@ void kQuantizeQ4(const float* X, void* buffer, int k, int type) {
|
||||||
////float scale = kQuantize0(QK, X, L, work, -7, 7);
|
////float scale = kQuantize0(QK, X, L, work, -7, 7);
|
||||||
std::memcpy(q, &scale, sizeof(scale)); q += sizeof(scale);
|
std::memcpy(q, &scale, sizeof(scale)); q += sizeof(scale);
|
||||||
for (int k=0; k<QK/2; ++k) q[k] = (L[2*k] + 8) | ((L[2*k+1] + 8) << 4);
|
for (int k=0; k<QK/2; ++k) q[k] = (L[2*k] + 8) | ((L[2*k+1] + 8) << 4);
|
||||||
} else {
|
} else if (type == 1) {
|
||||||
auto result = kQuantize1(QK, X, L, tmpX, work, 7);
|
auto result = kQuantize1(QK, X, L, tmpX, work, 7);
|
||||||
std::memcpy(q, &result.second, sizeof(result.second)); q += sizeof(result.second);
|
std::memcpy(q, &result.second, sizeof(result.second)); q += sizeof(result.second);
|
||||||
std::memcpy(q, &result.first, sizeof(result.first)); q += sizeof(result.first);
|
std::memcpy(q, &result.first, sizeof(result.first)); q += sizeof(result.first);
|
||||||
for (int k=0; k<QK/2; ++k) q[k] = L[2*k] | (L[2*k+1] << 4);
|
for (int k=0; k<QK/2; ++k) q[k] = L[2*k] | (L[2*k+1] << 4);
|
||||||
|
} else {
|
||||||
|
auto result = type == 2 ? kQuantize1(QK, X, L, tmpX, work, 15) : kQuantize1Fast(QK, X, L, 31);
|
||||||
|
auto afp16 = ggml_fp32_to_fp16(result.first);
|
||||||
|
auto bfp16 = ggml_fp32_to_fp16(result.second);
|
||||||
|
std::memcpy(q, &afp16, sizeof(afp16)); q += sizeof(afp16);
|
||||||
|
std::memcpy(q, &bfp16, sizeof(bfp16)); q += sizeof(bfp16);
|
||||||
|
auto u = (uint32_t*)q;
|
||||||
|
*u = 0;
|
||||||
|
q += sizeof(uint32_t);
|
||||||
|
uint32_t m = 1u;
|
||||||
|
for (int k=0; k<QK/2; ++k) {
|
||||||
|
auto l1 = L[2*k], l2 = L[2*k+1];
|
||||||
|
if (l1 > 15) { l1 -= 16; *u |= m; }
|
||||||
|
m <<= 1;
|
||||||
|
if (l2 > 15) { l2 -= 16; *u |= m; }
|
||||||
|
m <<= 1;
|
||||||
|
q[k] = l1 | (l2 << 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -318,6 +459,14 @@ void kQuantizeQ4_1(const float* x, void* buffer, int k) {
|
||||||
kQuantizeQ4(x, buffer, k, 1);
|
kQuantizeQ4(x, buffer, k, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kQuantizeQ5_1(const float* x, void* buffer, int k) {
|
||||||
|
kQuantizeQ4(x, buffer, k, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kQuantizeQ5_1_Fast(const float* x, void* buffer, int k) {
|
||||||
|
kQuantizeQ4(x, buffer, k, 3);
|
||||||
|
}
|
||||||
|
|
||||||
size_t kQuantizeQ4_0H(const float* x, void* buffer, int k, int64_t* hist) {
|
size_t kQuantizeQ4_0H(const float* x, void* buffer, int k, int64_t* hist) {
|
||||||
kQuantizeQ4(x, buffer, k, 0);
|
kQuantizeQ4(x, buffer, k, 0);
|
||||||
collectHisto(k, buffer, hist, 0);
|
collectHisto(k, buffer, hist, 0);
|
||||||
|
@ -330,4 +479,42 @@ size_t kQuantizeQ4_1H(const float* x, void* buffer, int k, int64_t* hist) {
|
||||||
return (k / QK) * kBucketSize1;
|
return (k / QK) * kBucketSize1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t kQuantizeQ5_1H(const float* x, void* buffer, int k, int64_t* hist) {
|
||||||
|
kQuantizeQ4(x, buffer, k, 2);
|
||||||
|
collectHisto(k, buffer, hist, 1);
|
||||||
|
return (k / QK) * kBucketSize1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t kQuantizeQ5_1H_Fast(const float* x, void* buffer, int k, int64_t* hist) {
|
||||||
|
kQuantizeQ4(x, buffer, k, 3);
|
||||||
|
collectHisto(k, buffer, hist, 1);
|
||||||
|
return (k / QK) * kBucketSize1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kDequantizeQ5_1(const void* x, float* y, int k) {
|
||||||
|
assert(k % QK == 0);
|
||||||
|
int n = k / QK;
|
||||||
|
auto data = (const uint8_t*)x;
|
||||||
|
for (int i=0; i<n; ++i) {
|
||||||
|
ggml_fp16_t afp16, bfp16;
|
||||||
|
std::memcpy(&afp16, data, sizeof(afp16)); data += sizeof(afp16);
|
||||||
|
std::memcpy(&bfp16, data, sizeof(bfp16)); data += sizeof(bfp16);
|
||||||
|
auto a = ggml_fp16_to_fp32(afp16);
|
||||||
|
auto b = ggml_fp16_to_fp32(bfp16);
|
||||||
|
uint32_t u;
|
||||||
|
std::memcpy(&u, data, sizeof(u)); data += sizeof(u);
|
||||||
|
uint32_t m = 1u;
|
||||||
|
for (int k=0; k<16; ++k) {
|
||||||
|
auto l1 = data[k] & 15, l2 = data[k] >> 4;
|
||||||
|
if (u & m) l1 += 16;
|
||||||
|
m <<= 1;
|
||||||
|
if (u & m) l2 += 16;
|
||||||
|
m <<= 1;
|
||||||
|
*y++ = a + b*l1;
|
||||||
|
*y++ = a + b*l2;
|
||||||
|
}
|
||||||
|
data += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,12 @@ size_t kQuantizeQ4_0H(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k
|
||||||
void kQuantizeQ4_1(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k);
|
void kQuantizeQ4_1(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k);
|
||||||
size_t kQuantizeQ4_1H(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k, int64_t* hist);
|
size_t kQuantizeQ4_1H(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k, int64_t* hist);
|
||||||
|
|
||||||
|
void kQuantizeQ5_1(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k);
|
||||||
|
size_t kQuantizeQ5_1H(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k, int64_t* hist);
|
||||||
|
void kQuantizeQ5_1_Fast(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k);
|
||||||
|
size_t kQuantizeQ5_1H_Fast(const float* GGML_RESTRICT x, void* GGML_RESTRICT y, int k, int64_t* hist);
|
||||||
|
void kDequantizeQ5_1(const void * GGML_RESTRICT x, float * GGML_RESTRICT y, int k);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue