#include #include #include #include #include namespace at::native { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ empty ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // We explicitly pass in scale and zero_point because we don't have the infra // ready to support quantizer in python frontend, once that is ready, we'll // change to use quantizer Tensor empty_affine_quantized( IntArrayRef size, std::optional dtype, std::optional layout, std::optional device, std::optional pin_memory, double scale, int64_t zero_point, std::optional optional_memory_format) { // See [Note: hacky wrapper removal for TensorOptions] TensorOptions options_ = TensorOptions().dtype(dtype).layout(layout).device(device).pinned_memory(pin_memory); TORCH_CHECK( !(options_.has_memory_format() && optional_memory_format.has_value()), "Cannot set memory_format both in TensorOptions and explicit argument; please delete " "the redundant setter."); auto options = options_.merge_memory_format(optional_memory_format); TORCH_CHECK( options.has_dtype(), "Must provide data type for Tensor creation functions."); return new_qtensor( size, options, make_per_tensor_affine_quantizer( scale, zero_point, typeMetaToScalarType(options.dtype()))); } Tensor empty_per_channel_affine_quantized( IntArrayRef size, const Tensor& scales, const Tensor& zero_points, int64_t axis, std::optional dtype, std::optional layout, std::optional device, std::optional pin_memory, std::optional optional_memory_format) { // See [Note: hacky wrapper removal for TensorOptions] TensorOptions options_ = TensorOptions().dtype(dtype).layout(layout).device(device).pinned_memory(pin_memory); TORCH_CHECK( !(options_.has_memory_format() && optional_memory_format.has_value()), "Cannot set memory_format both in TensorOptions and explicit argument; please delete " "the redundant setter."); auto options = options_.merge_memory_format(optional_memory_format); TORCH_CHECK( options.has_dtype(), "Must provide data type for Tensor creation functions."); QuantizerPtr quantizer = make_per_channel_affine_quantizer( scales.to(options.device()), zero_points.to(options.device()), axis, typeMetaToScalarType(options.dtype())); return new_qtensor( size, options, std::move(quantizer)); } Tensor empty_unknown_quantized( IntArrayRef size, std::optional dtype, std::optional layout, std::optional device, std::optional pin_memory, std::optional optional_memory_format) { // See [Note: hacky wrapper removal for TensorOptions] TensorOptions options_ = TensorOptions().dtype(dtype).layout(layout).device(device).pinned_memory(pin_memory); TORCH_CHECK( !(options_.has_memory_format() && optional_memory_format.has_value()), "Cannot set memory_format both in TensorOptions and explicit argument; please delete " "the redundant setter."); auto options = options_.merge_memory_format(optional_memory_format); TORCH_CHECK( options.has_dtype(), "Must provide data type for Tensor creation functions."); QuantizerPtr quantizer = make_unknown_quantizer(typeMetaToScalarType(options.dtype())); return new_qtensor(size, options, std::move(quantizer)); } Tensor empty_strided_unknown_quantized( IntArrayRef size, IntArrayRef strided, std::optional dtype, std::optional layout, std::optional device, std::optional pin_memory) { TORCH_CHECK(false, "empty_strided not supported on quantized tensors yet see https://github.com/pytorch/pytorch/issues/74540") } // Provide better error message if dtype is wrong Tensor empty_affine_quantized_other_backends_stub( IntArrayRef, std::optional, std::optional, std::optional, std::optional, double, int64_t, std::optional) { TORCH_CHECK(false, "Creation of quantized tensor requires quantized dtype like torch.quint8"); } Tensor empty_per_channel_affine_quantized_other_backends_stub( IntArrayRef, const Tensor&, const Tensor&, int64_t, std::optional, std::optional, std::optional, std::optional, std::optional) { TORCH_CHECK(false, "Creation of quantized tensor requires quantized dtype like torch.quint8"); } // Create an empty quantized Tensor with size, based on the options // and quantization parameters of the input quantized Tensor Tensor empty_quantized( IntArrayRef size, const Tensor& qtensor, std::optional dtype, std::optional layout, std::optional device, std::optional pin_memory, std::optional memory_format) { TensorOptions specified_options = TensorOptions().dtype(dtype).layout(layout).device(device).pinned_memory(pin_memory); TORCH_CHECK( !(specified_options.has_memory_format() && memory_format.has_value()), "Cannot set memory_format both in TensorOptions and explicit argument; please delete " "the redundant setter."); TensorOptions options = qtensor.options() .merge_in(specified_options) .merge_memory_format(memory_format); Tensor output; if (qtensor.qscheme() == kPerTensorAffine) { output = at::_empty_affine_quantized( size, options, qtensor.q_scale(), qtensor.q_zero_point()); } else if ( qtensor.qscheme() == kPerChannelAffine || qtensor.qscheme() == kPerChannelAffineFloatQParams) { output = at::_empty_per_channel_affine_quantized( size, qtensor.q_per_channel_scales(), qtensor.q_per_channel_zero_points(), qtensor.q_per_channel_axis(), options); } else { TORCH_CHECK( false, "QScheme not supported by empty_quantized:", toString(qtensor.qscheme())); } return output; } } // namespace at::native