| 1147 | |
| 1148 | template <typename T, typename U> |
| 1149 | void quantize( |
| 1150 | const T* w, |
| 1151 | U* out, |
| 1152 | T* scales, |
| 1153 | T* biases, |
| 1154 | int bits, |
| 1155 | int group_size, |
| 1156 | size_t w_size) { |
| 1157 | float n_bins = (1 << bits) - 1; |
| 1158 | float eps = 1e-7; |
| 1159 | |
| 1160 | bool power_of_2_bits = is_power_of_2(bits); |
| 1161 | int el_per_int = get_pack_factor(bits, 32); |
| 1162 | int bytes_per_pack = get_bytes_per_pack(bits); |
| 1163 | int int_per_group = group_size * bytes_per_pack / el_per_int; |
| 1164 | size_t n_groups = w_size / group_size; |
| 1165 | |
| 1166 | for (size_t i = 0; i < n_groups; ++i) { |
| 1167 | size_t w_idx = i * group_size; |
| 1168 | float w_min = std::numeric_limits<float>::infinity(); |
| 1169 | float w_max = -w_min; |
| 1170 | for (int j = 0; j < group_size; ++j) { |
| 1171 | w_max = std::max(w_max, (float)w[w_idx + j]); |
| 1172 | w_min = std::min(w_min, (float)w[w_idx + j]); |
| 1173 | } |
| 1174 | bool mask = std::abs(w_min) > std::abs(w_max); |
| 1175 | float scale = std::max((w_max - w_min) / n_bins, eps); |
| 1176 | scale = mask ? scale : -scale; |
| 1177 | |
| 1178 | float edge = mask ? w_min : w_max; |
| 1179 | float q0 = std::rint(edge / scale); |
| 1180 | float bias = 0; |
| 1181 | if (q0 != 0) { |
| 1182 | scale = edge / q0; |
| 1183 | bias = edge; |
| 1184 | } |
| 1185 | size_t out_idx = i * int_per_group; |
| 1186 | for (int j = 0; j < int_per_group / bytes_per_pack; ++j) { |
| 1187 | uint64_t out_el = 0; |
| 1188 | for (int k = 0; k < el_per_int; ++k) { |
| 1189 | float w_el = w[w_idx + j * el_per_int + k]; |
| 1190 | w_el = std::rint((w_el - bias) / scale); |
| 1191 | w_el = std::min(std::max(w_el, 0.0f), n_bins); |
| 1192 | out_el |= static_cast<uint64_t>(w_el) << (k * bits); |
| 1193 | } |
| 1194 | if (power_of_2_bits) { |
| 1195 | out[out_idx + j] = out_el; |
| 1196 | } else if (bits == 5) { |
| 1197 | out[out_idx + bytes_per_pack * j] = out_el & 0xff; |
| 1198 | out[out_idx + bytes_per_pack * j + 1] = (out_el & 0xff00) >> 8; |
| 1199 | out[out_idx + bytes_per_pack * j + 2] = (out_el & 0xff0000) >> 16; |
| 1200 | out[out_idx + bytes_per_pack * j + 3] = (out_el & 0xff000000) >> 24; |
| 1201 | out[out_idx + bytes_per_pack * j + 4] = (out_el & 0xff00000000) >> 32; |
| 1202 | } else { |
| 1203 | out[out_idx + bytes_per_pack * j] = out_el & 0xff; |
| 1204 | out[out_idx + bytes_per_pack * j + 1] = (out_el & 0xff00) >> 8; |
| 1205 | out[out_idx + bytes_per_pack * j + 2] = (out_el & 0xff0000) >> 16; |
| 1206 | } |
nothing calls this directly
no test coverage detected