| 4906 | } |
| 4907 | |
| 4908 | std::vector<array> quantize( |
| 4909 | const array& w, |
| 4910 | std::optional<int> group_size_ /* = std::nullopt */, |
| 4911 | std::optional<int> bits_ /* = std::nullopt */, |
| 4912 | const std::string& mode /* = "affine" */, |
| 4913 | const std::optional<array>& global_scale /* = std::nullopt */, |
| 4914 | StreamOrDevice s /* = {} */) { |
| 4915 | auto qmode = string_to_quantization_mode(mode, "quantize"); |
| 4916 | auto [group_size, bits] = |
| 4917 | quantization_params_from_mode(qmode, group_size_, bits_); |
| 4918 | if (!issubdtype(w.dtype(), floating)) { |
| 4919 | std::ostringstream msg; |
| 4920 | msg << "[quantize] Only real floating types can be quantized " |
| 4921 | << "but w has type " << w.dtype() << "."; |
| 4922 | throw std::invalid_argument(msg.str()); |
| 4923 | } |
| 4924 | |
| 4925 | if (w.ndim() < 2) { |
| 4926 | std::ostringstream msg; |
| 4927 | msg << "[quantize] The matrix to be quantized must have at least 2 dimension " |
| 4928 | << "but it has only " << w.ndim() << "."; |
| 4929 | throw std::invalid_argument(msg.str()); |
| 4930 | } |
| 4931 | |
| 4932 | if ((w.shape(-1) % group_size) != 0) { |
| 4933 | std::ostringstream msg; |
| 4934 | msg << "[quantize] The last dimension of the matrix needs to be divisible by " |
| 4935 | << "the quantization group size " << group_size |
| 4936 | << ". However the provided " |
| 4937 | << " matrix has shape " << w.shape(); |
| 4938 | throw std::invalid_argument(msg.str()); |
| 4939 | } |
| 4940 | if (to_stream(s).device == Device::gpu && metal::is_available() && |
| 4941 | global_scale.has_value()) { |
| 4942 | std::ostringstream msg; |
| 4943 | msg << "[quantize] Global scale is not supported on the Metal backend."; |
| 4944 | throw std::invalid_argument(msg.str()); |
| 4945 | } |
| 4946 | validate_global_scale("quantize", qmode, global_scale); |
| 4947 | if (qmode == QuantizationMode::Affine) { |
| 4948 | return affine_quantize(w, group_size, bits, s); |
| 4949 | } else { |
| 4950 | return fp_quantize(w, group_size, bits, qmode, global_scale, to_stream(s)); |
| 4951 | } |
| 4952 | } |
| 4953 | |
| 4954 | array affine_dequantize( |
| 4955 | const array& w, |
no test coverage detected