| 8957 | }; |
| 8958 | |
| 8959 | static void llama_convert_tensor_internal( |
| 8960 | struct ggml_tensor * tensor, std::vector<no_init<float>> & output, std::vector<std::thread> & workers, |
| 8961 | const size_t nelements, const int nthread |
| 8962 | ) { |
| 8963 | if (output.size() < nelements) { |
| 8964 | output.resize(nelements); |
| 8965 | } |
| 8966 | float * f32_output = (float *) output.data(); |
| 8967 | |
| 8968 | ggml_type_traits_t qtype; |
| 8969 | if (ggml_is_quantized(tensor->type)) { |
| 8970 | qtype = ggml_internal_get_type_traits(tensor->type); |
| 8971 | if (qtype.to_float == NULL) { |
| 8972 | throw std::runtime_error(format("type %s unsupported for integer quantization: no dequantization available", ggml_type_name(tensor->type))); |
| 8973 | } |
| 8974 | } else if (tensor->type != GGML_TYPE_F16) { |
| 8975 | throw std::runtime_error(format("cannot dequantize/convert tensor type %s", ggml_type_name(tensor->type))); |
| 8976 | } |
| 8977 | |
| 8978 | if (nthread < 2) { |
| 8979 | if (tensor->type == GGML_TYPE_F16) { |
| 8980 | ggml_fp16_to_fp32_row((ggml_fp16_t *)tensor->data, f32_output, nelements); |
| 8981 | } else if (ggml_is_quantized(tensor->type)) { |
| 8982 | qtype.to_float(tensor->data, f32_output, nelements); |
| 8983 | } else { |
| 8984 | GGML_ASSERT(false); // unreachable |
| 8985 | } |
| 8986 | return; |
| 8987 | } |
| 8988 | |
| 8989 | auto block_size = tensor->type == GGML_TYPE_F16 ? 1 : (size_t)ggml_blck_size(tensor->type); |
| 8990 | auto block_size_bytes = ggml_type_size(tensor->type); |
| 8991 | |
| 8992 | GGML_ASSERT(nelements % block_size == 0); |
| 8993 | auto nblocks = nelements / block_size; |
| 8994 | auto blocks_per_thread = nblocks / nthread; |
| 8995 | auto spare_blocks = nblocks - (blocks_per_thread * nthread); // if blocks aren't divisible by thread count |
| 8996 | |
| 8997 | for (auto tnum = 0, in_buff_offs = 0, out_buff_offs = 0; tnum < nthread; tnum++) { |
| 8998 | auto thr_blocks = blocks_per_thread + (tnum == nthread - 1 ? spare_blocks : 0); // num blocks for this thread |
| 8999 | auto thr_elems = thr_blocks * block_size; // number of elements for this thread |
| 9000 | auto thr_block_bytes = thr_blocks * block_size_bytes; // number of input bytes for this thread |
| 9001 | |
| 9002 | auto compute = [qtype] (ggml_type typ, uint8_t * inbuf, float * outbuf, int nels) { |
| 9003 | if (typ == GGML_TYPE_F16) { |
| 9004 | ggml_fp16_to_fp32_row((ggml_fp16_t *)inbuf, outbuf, nels); |
| 9005 | } else { |
| 9006 | qtype.to_float(inbuf, outbuf, nels); |
| 9007 | } |
| 9008 | }; |
| 9009 | workers.emplace_back(compute, tensor->type, (uint8_t *) tensor->data + in_buff_offs, f32_output + out_buff_offs, thr_elems); |
| 9010 | in_buff_offs += thr_block_bytes; |
| 9011 | out_buff_offs += thr_elems; |
| 9012 | } |
| 9013 | for (auto & w : workers) { w.join(); } |
| 9014 | workers.clear(); |
| 9015 | } |
| 9016 |
no test coverage detected