Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement chunk for different backends #1032

Merged
merged 5 commits into from
Dec 20, 2023
Merged

Implement chunk for different backends #1032

merged 5 commits into from
Dec 20, 2023

Conversation

Kelvinyu1117
Copy link
Contributor

@Kelvinyu1117 Kelvinyu1117 commented Dec 1, 2023

Pull Request Template

Checklist

  • Confirmed that run-checks all script has been executed.
  • Made sure the book is up to date with changes in this PR.

Related Issues/PRs

#970

Changes

This PR is in progress, mainly utilizing the backend implementation for chunk() instead of the default, currently only bool_chunk was implemented and encountered issues for burn-fusion.

Testing

As it is still in progress, it has not yet been tested.

@Kelvinyu1117
Copy link
Contributor Author

Kelvinyu1117 commented Dec 1, 2023

Currently, this PR has an error of not implementing the traits:

error[E0046]: not all trait items implemented, missing: `bool_chunk`
  --> burn-fusion/src/ops/boolean.rs:17:1
   |
17 | impl<B: FusionBackend> BoolTensorOps<Self> for Fusion<B> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bool_chunk` in implementation
   |
   = help: implement the missing item: `fn bool_chunk(_: <backend::Fusion<B> as burn_tensor::backend::Backend>::BoolTensorPrimitive<D>, _: usize, _: usize) -> std::vec::Vec<<backend::Fusion<B> as burn_tensor::backend::Backend>::BoolTensorPrimitive<D>> { todo!() }`

I think once we come up with the solution for burn-fusion, the implementation of other data types (Int/Float) will be trivial.

@Kelvinyu1117 Kelvinyu1117 marked this pull request as draft December 2, 2023 06:02
@Kelvinyu1117 Kelvinyu1117 marked this pull request as ready for review December 2, 2023 16:08
@Kelvinyu1117
Copy link
Contributor Author

The current solution is to have a default implementation on all the ops, such that the backend can fall back to the default.

Copy link
Member

@nathanielsimard nathanielsimard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can remove the default function implementation of chunk and narrow in the Kind API. I think you should create files in burn_tensor for narrow and chunk where implementations will be located, which can reduce code duplication.

let tensor = tensor.tensor.narrow(dim, start, length);
match tensor {
Ok(tensor) => CandleTensor::new(tensor),
Err(e) => panic!("error chunk from Candle"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error chunk => error narrow

if i == dim {
start..(start + length)
} else {
0..Self::shape(&tensor).dims[i]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would extract the shape before the loop, just a bit cleaner imo.

Comment on lines 1187 to 1192
fn chunk<const D: usize>(
tensor: Self::Primitive<D>,
chunks: usize,
dim: usize,
) -> Vec<Self::Primitive<D>> {
let size = Self::shape(&tensor).dims[dim];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default implementation should be in the Backend trait, not in the API Kind trait system.

So the change would be =>

Extract those functions into their own modules burn-tensor/src/ops/chunk.rs and burn-tensor/src/ops/narrow.rs. In the TensorOps, IntTensorOps and BoolTensorOps trait, we should call those functions by default, so backends are not forced to implement the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm the interfaces, I presume they should be the following right?:

pub(crate) fn chunk<B: Backend, const D: usize, K: TensorKind>(
    tensor: Tensor<B, D, K>,
    chunks: usize,
    dim: usize,
) -> Vec<Tensor<B, D, K>> {
}

pub(crate) fn narrow<B: Backend, const D: usize, K: TensorKind>(
    tensor: Tensor<B, D, K>,
    dim: usize,
    start: usize,
    length: usize,
) -> Tensor<B, D, K> {
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kelvinyu1117 Yes sorry for the delay, I wasn't available last week 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is refactored. Please have a look, thanks.

Copy link
Member

@louisfd louisfd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, it's good that we can leverage tch and candle implementations!
It appears we have worked a bit in parallel, see my other comment.

///
/// A vectors of tensors
///
fn chunk<const D: usize>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you have started your branch before #1006 was merged.
In #1006 we modified the default chunk algorithm --don't mind the name of the PR which is about fixing the docs, at first I thought the doc was wrong and the code was right, but in the end the doc was right and the code was wrong.
Could you please adjust the algorithm so it passes the test in #1006 (or in main as #1006 was merged) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, let me work on that.

Copy link

codecov bot commented Dec 18, 2023

Codecov Report

Attention: 213 lines in your changes are missing coverage. Please review.

Comparison is base (4fb5b74) 85.63% compared to head (e1e9eee) 85.33%.
Report is 1 commits behind head on main.

Files Patch % Lines
burn-candle/src/ops/base.rs 0.00% 24 Missing ⚠️
burn-tch/src/ops/base.rs 0.00% 24 Missing ⚠️
burn-autodiff/src/ops/bool_tensor.rs 0.00% 15 Missing ⚠️
burn-autodiff/src/ops/int_tensor.rs 0.00% 15 Missing ⚠️
burn-candle/src/ops/bool_tensor.rs 0.00% 15 Missing ⚠️
burn-candle/src/ops/int_tensor.rs 0.00% 15 Missing ⚠️
burn-candle/src/ops/tensor.rs 0.00% 15 Missing ⚠️
burn-tch/src/ops/bool_tensor.rs 0.00% 15 Missing ⚠️
burn-tch/src/ops/int_tensor.rs 0.00% 15 Missing ⚠️
burn-tch/src/ops/tensor.rs 0.00% 15 Missing ⚠️
... and 3 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1032      +/-   ##
==========================================
- Coverage   85.63%   85.33%   -0.30%     
==========================================
  Files         507      509       +2     
  Lines       54074    54324     +250     
==========================================
+ Hits        46305    46357      +52     
- Misses       7769     7967     +198     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@louisfd
Copy link
Member

louisfd commented Dec 18, 2023

Thanks for the change, looks good to me now

Copy link
Member

@nathanielsimard nathanielsimard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some smalls changes, but it's getting ready to be merged.

Comment on lines 1391 to 1397
// fn chunk<const D: usize>(
// tensor: Self::Primitive<D>,
// chunks: usize,
// dim: usize,
// ) -> Vec<Self::Primitive<D>> {
// B::bool_chunk(tensor, chunks, dim)
// }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deed code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

Comment on lines 4 to 22
/// Split the tensor along the given dimension into chunks.
///
/// # Arguments
///
/// * `tensor` - The tensor.
/// * `chunks` - The number of chunks to be produced
/// * `times` - The dimension along which the tensor will be split.
///
/// # Returns
///
/// A vectors of tensors
///
/// # Remarks
///
/// This is a fallback solution that used only when the backend doesn't have the corresponding implementation.
/// Ideally, it is supposed to be implemented by the backend and the backend implementation will be resolved
/// by static dispatch. It is not designed for direct usage by users, and not recommended to import
/// or use this function directly.
///
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small details, but I think spacing between the comments and the imports would be nice. Also, the last empty line of the comment isn't necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@nathanielsimard nathanielsimard merged commit 7c6f017 into tracel-ai:main Dec 20, 2023
13 of 14 checks passed
@Kelvinyu1117 Kelvinyu1117 deleted the kelvin/feature/chunk-optimize branch December 21, 2023 09:43
syl20bnr added a commit to syl20bnr/burn that referenced this pull request Jan 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants