Run quantization function for a single layer and update error stats
| 166 | |
| 167 | // Run quantization function for a single layer and update error stats |
| 168 | static void test_roundtrip_on_layer( |
| 169 | std::string & name, bool print_layer_stats, const ggml_type_traits_t & qfns, bool use_reference, |
| 170 | const ggml_tensor * layer, std::vector<float> & input_scratch, std::vector<char> & quantized_scratch, |
| 171 | std::vector<float> & output_scratch, error_stats & total_error, int max_thread = 0 |
| 172 | ) { |
| 173 | assert(tensor_is_contiguous(layer)); |
| 174 | error_stats layer_error {}; |
| 175 | uint64_t nelements = ggml_nelements(layer); |
| 176 | |
| 177 | float* input_scratch_ptr = nullptr; |
| 178 | if (layer->type == GGML_TYPE_F16) { |
| 179 | if (input_scratch.size() < nelements) input_scratch.resize(nelements); |
| 180 | input_scratch_ptr = input_scratch.data(); |
| 181 | } |
| 182 | if (quantized_scratch.size() < 4*nelements) quantized_scratch.resize(4*nelements); |
| 183 | if (output_scratch.size() < nelements) output_scratch.resize(nelements); |
| 184 | |
| 185 | if (max_thread < 1) max_thread = std::thread::hardware_concurrency(); |
| 186 | int chunk_size = 32*512; |
| 187 | int num_chunks = (nelements + chunk_size - 1)/chunk_size; |
| 188 | |
| 189 | if (num_chunks < 2 || max_thread < 2) { |
| 190 | test_roundtrip_on_chunk(layer, 0, nelements, qfns, use_reference, input_scratch_ptr, quantized_scratch.data(), |
| 191 | output_scratch.data(), print_layer_stats ? layer_error : total_error); |
| 192 | } else { |
| 193 | auto & stats = print_layer_stats ? layer_error : total_error; |
| 194 | std::mutex mutex; |
| 195 | uint64_t counter = 0; |
| 196 | auto compute = [&mutex, &counter, &stats, &qfns, nelements, layer, use_reference, input_scratch_ptr, |
| 197 | &quantized_scratch, &output_scratch, chunk_size] () { |
| 198 | error_stats local_stats {}; |
| 199 | while (true) { |
| 200 | std::unique_lock<std::mutex> lock(mutex); |
| 201 | uint64_t offset = counter; counter += chunk_size; |
| 202 | if (offset >= nelements) { |
| 203 | combine_error_stats(stats, local_stats); |
| 204 | break; |
| 205 | } |
| 206 | lock.unlock(); |
| 207 | uint64_t chunk = offset + chunk_size < nelements ? chunk_size : nelements - offset; |
| 208 | test_roundtrip_on_chunk(layer, offset, chunk, qfns, use_reference, input_scratch_ptr + offset, |
| 209 | quantized_scratch.data() + 4*offset, output_scratch.data() + offset, local_stats); |
| 210 | } |
| 211 | }; |
| 212 | int nthread = std::min(num_chunks, max_thread); |
| 213 | std::vector<std::thread> workers(nthread-1); |
| 214 | for (auto& w : workers) w = std::thread(compute); |
| 215 | compute(); |
| 216 | for (auto& w : workers) w.join(); |
| 217 | } |
| 218 | |
| 219 | if (print_layer_stats) { |
| 220 | print_error_stats(name, layer_error, false); |
| 221 | combine_error_stats(total_error, layer_error); |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | int main(int argc, char ** argv) { |
no test coverage detected