Skip to content

Commit

Permalink
Add ops w/ default implementation for QTensorOps (#2125)
Browse files Browse the repository at this point in the history
* Add q_* ops to match float ops

* Refactor q_* ops w/ dequant_op_quant macro

* Comparison ops are already implemented by default to compare dequantized values

* Add default arg min/max implementation and fix tch implementation

* Avoid division by zero scale

* Add default q_gather implementation (tch does not support on quantized tensor)

* Add warning instead for tch quantize_dynamic

* Call chunk backend implementation

* Add QFloat check for q_ ops

* Add tch q_min/max_dim_with_indices

* Add q_ ops tests

* Clippy fix

* Remove dead code/comments

* Fix quantization tests precision

* Set higher tolerance for ndarray backend

* Remove comment
  • Loading branch information
laggui authored Sep 9, 2024
1 parent 9e9451b commit eb899db
Show file tree
Hide file tree
Showing 67 changed files with 7,245 additions and 92 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

84 changes: 83 additions & 1 deletion crates/burn-autodiff/src/ops/qtensor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::ops::Range;

use burn_tensor::{
backend::Backend,
ops::{FloatTensor, QTensorOps, QuantizedTensor},
ops::{FloatTensor, IntTensor, QTensorOps, QuantizedTensor},
quantization::{QuantizationParametersPrimitive, QuantizationScheme},
Device, Shape, TensorData,
};
Expand All @@ -23,6 +25,13 @@ impl<B: Backend, C: CheckpointStrategy> QTensorOps<Self> for Autodiff<B, C> {
todo!() // required for QAT
}

fn quantize_dynamic<const D: usize>(
_tensor: FloatTensor<Self, D>,
_scheme: &QuantizationScheme,
) -> QuantizedTensor<Self, D> {
todo!()
}

fn dequantize<const D: usize>(_tensor: QuantizedTensor<Self, D>) -> FloatTensor<Self, D> {
todo!()
}
Expand All @@ -35,6 +44,13 @@ impl<B: Backend, C: CheckpointStrategy> QTensorOps<Self> for Autodiff<B, C> {
B::q_device(tensor)
}

fn q_to_device<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_device: &Device<Self>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_reshape<const D1: usize, const D2: usize>(
tensor: QuantizedTensor<Self, D1>,
shape: Shape<D2>,
Expand All @@ -45,4 +61,70 @@ impl<B: Backend, C: CheckpointStrategy> QTensorOps<Self> for Autodiff<B, C> {
async fn q_into_data<const D: usize>(tensor: QuantizedTensor<Self, D>) -> TensorData {
B::q_into_data(tensor).await
}

fn q_swap_dims<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim1: usize,
_dim2: usize,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_permute<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: [usize; D],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_flip<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: &[usize],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_gather<const D: usize>(
_dim: usize,
_tensor: QuantizedTensor<Self, D>,
_indices: IntTensor<Self, D>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_select<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim: usize,
_indices: IntTensor<Self, 1>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_slice<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_ranges: [Range<usize>; D2],
) -> QuantizedTensor<Self, D1> {
unimplemented!()
}

fn q_argmax<const D: usize>(
tensor: QuantizedTensor<Self, D>,
dim: usize,
) -> IntTensor<Self, D> {
B::q_argmax(tensor, dim)
}

fn q_argmin<const D: usize>(
tensor: QuantizedTensor<Self, D>,
dim: usize,
) -> IntTensor<Self, D> {
B::q_argmin(tensor, dim)
}

fn q_expand<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_shape: Shape<D2>,
) -> QuantizedTensor<Self, D2> {
unimplemented!()
}
}
63 changes: 62 additions & 1 deletion crates/burn-candle/src/ops/qtensor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::ops::Range;

use burn_tensor::{
backend::Backend,
ops::{FloatTensor, QTensorOps, QuantizedTensor},
ops::{FloatTensor, IntTensor, QTensorOps, QuantizedTensor},
quantization::{QuantizationParametersPrimitive, QuantizationScheme, QuantizationStrategy},
DType, Device, Shape, TensorData,
};
Expand Down Expand Up @@ -38,6 +40,13 @@ impl<F: FloatCandleElement, I: IntCandleElement> QTensorOps<Self> for Candle<F,
super::base::device(&tensor.qtensor)
}

fn q_to_device<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_device: &Device<Self>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_reshape<const D1: usize, const D2: usize>(
tensor: QuantizedTensor<Self, D1>,
shape: Shape<D2>,
Expand All @@ -51,4 +60,56 @@ impl<F: FloatCandleElement, I: IntCandleElement> QTensorOps<Self> for Candle<F,
async fn q_into_data<const D: usize>(tensor: QuantizedTensor<Self, D>) -> TensorData {
unimplemented!()
}

fn q_swap_dims<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim1: usize,
_dim2: usize,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_permute<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: [usize; D],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_flip<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: &[usize],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_gather<const D: usize>(
_dim: usize,
_tensor: QuantizedTensor<Self, D>,
_indices: IntTensor<Self, D>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_select<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim: usize,
_indices: IntTensor<Self, 1>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_slice<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_ranges: [Range<usize>; D2],
) -> QuantizedTensor<Self, D1> {
unimplemented!()
}

fn q_expand<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_shape: Shape<D2>,
) -> QuantizedTensor<Self, D2> {
unimplemented!()
}
}
70 changes: 69 additions & 1 deletion crates/burn-fusion/src/ops/qtensor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::ops::Range;

use burn_tensor::{
backend::Backend,
ops::{QTensorOps, QuantizedTensor},
ops::{IntTensor, QTensorOps, QuantizedTensor},
quantization::{QuantizationParametersPrimitive, QuantizationScheme},
Device, Shape, TensorData,
};
Expand All @@ -23,6 +25,13 @@ impl<B: FusionBackend> QTensorOps<Self> for Fusion<B> {
unimplemented!()
}

fn quantize_dynamic<const D: usize>(
_tensor: <Self as Backend>::FloatTensorPrimitive<D>,
_scheme: &QuantizationScheme,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn dequantize<const D: usize>(
_tensor: <Self as Backend>::QuantizedTensorPrimitive<D>,
) -> <Self as Backend>::FloatTensorPrimitive<D> {
Expand All @@ -37,6 +46,13 @@ impl<B: FusionBackend> QTensorOps<Self> for Fusion<B> {
tensor.qtensor.client.device().clone()
}

fn q_to_device<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_device: &Device<Self>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_reshape<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_shape: Shape<D2>,
Expand All @@ -47,4 +63,56 @@ impl<B: FusionBackend> QTensorOps<Self> for Fusion<B> {
async fn q_into_data<const D: usize>(_tensor: QuantizedTensor<Self, D>) -> TensorData {
unimplemented!()
}

fn q_swap_dims<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim1: usize,
_dim2: usize,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_permute<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: [usize; D],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_flip<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: &[usize],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_gather<const D: usize>(
_dim: usize,
_tensor: QuantizedTensor<Self, D>,
_indices: IntTensor<Self, D>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_select<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim: usize,
_indices: IntTensor<Self, 1>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_slice<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_ranges: [Range<usize>; D2],
) -> QuantizedTensor<Self, D1> {
unimplemented!()
}

fn q_expand<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_shape: Shape<D2>,
) -> QuantizedTensor<Self, D2> {
unimplemented!()
}
}
1 change: 1 addition & 0 deletions crates/burn-jit/src/ops/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub(crate) fn from_data<R: JitRuntime, E: JitElement, const D: usize>(
data: TensorData,
device: &R::Device,
) -> JitTensor<R, E, D> {
// TODO: from_data QFloat should not convert
let shape: Shape<D> = (&data.shape).into();
let client = R::client(device);
let buffer = client.create(data.convert::<E>().as_bytes());
Expand Down
63 changes: 62 additions & 1 deletion crates/burn-jit/src/ops/qtensor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::ops::Range;

use burn_tensor::{
ops::{FloatTensor, QTensorOps, QuantizedTensor},
ops::{FloatTensor, IntTensor, QTensorOps, QuantizedTensor},
quantization::{QuantizationParametersPrimitive, QuantizationScheme},
Device, Shape, TensorData,
};
Expand Down Expand Up @@ -39,6 +41,13 @@ where
tensor.qtensor.device.clone()
}

fn q_to_device<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_device: &Device<Self>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_reshape<const D1: usize, const D2: usize>(
tensor: QuantizedTensor<Self, D1>,
shape: Shape<D2>,
Expand All @@ -52,4 +61,56 @@ where
async fn q_into_data<const D: usize>(_tensor: QuantizedTensor<Self, D>) -> TensorData {
unimplemented!()
}

fn q_swap_dims<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim1: usize,
_dim2: usize,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_permute<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: [usize; D],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_flip<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_axes: &[usize],
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_gather<const D: usize>(
_dim: usize,
_tensor: QuantizedTensor<Self, D>,
_indices: IntTensor<Self, D>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_select<const D: usize>(
_tensor: QuantizedTensor<Self, D>,
_dim: usize,
_indices: IntTensor<Self, 1>,
) -> QuantizedTensor<Self, D> {
unimplemented!()
}

fn q_slice<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_ranges: [Range<usize>; D2],
) -> QuantizedTensor<Self, D1> {
unimplemented!()
}

fn q_expand<const D1: usize, const D2: usize>(
_tensor: QuantizedTensor<Self, D1>,
_shape: Shape<D2>,
) -> QuantizedTensor<Self, D2> {
unimplemented!()
}
}
1 change: 1 addition & 0 deletions crates/burn-ndarray/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mod tests {
use alloc::vec;

burn_tensor::testgen_all!();
burn_tensor::testgen_quantization!();

#[cfg(feature = "std")]
burn_autodiff::testgen_all!();
Expand Down
Loading

0 comments on commit eb899db

Please sign in to comment.