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

Make compatible with thumbv6m-none-eabi #1384

Merged
merged 1 commit into from
Aug 2, 2024

Conversation

BjornTheProgrammer
Copy link
Contributor

Changes

Add the crates portable-atomic and portable-atomic-util to make the Arc used in the code compatible with the thumbv6m-none-eabi target. Also note that this change will probably make ndarray work on more targets than just the thumbv6m-none-eabi target.

Considerations

Those two crates are imported from a GitHub revision. It might be best to wait for an official release to crates.io, but I'm not sure if that's important.

This has also been tested and confirmed to work on a Raspberry Pi Pico.

Cargo.toml Outdated Show resolved Hide resolved
@antimora
Copy link

Burn project's Ndarray backend would very much appreciate if this PR is merged. We have a long outstanding issue: tracel-ai/burn#302

@BjornTheProgrammer
Copy link
Contributor Author

@bluss, do you have any more concerns about this pull request? If so, I would love to see if I can address them!

@bluss
Copy link
Member

bluss commented Jul 30, 2024

Clippy is fixed on current master. I just approved the CI run.

Not sure if I can review sensibly.

@BjornTheProgrammer
Copy link
Contributor Author

BjornTheProgrammer commented Jul 30, 2024

What issues make it so you might be unable to review sensibly? I can help with hardware if you need it. Additionally, I could write a test to check that it compiles correctly.

I did forget to mention, but here are the commands needed to compile for thumbv6m-none-eabi.

  1. rustup target add thumbv6m-none-eabi
  2. cargo build --target thumbv6m-none-eabi --no-default-features --features portable-atomic --features critical-section

@bluss
Copy link
Member

bluss commented Jul 30, 2024

@BjornTheProgrammer Main reason is I'm a quite bad maintainer, as you can see, so it takes some time. So always wary to take on more complexity especially in an area that is not something I know about.

use alloc::sync::Arc;

#[cfg(feature = "portable-atomic")]
use portable_atomic_util::Arc;
Copy link
Member

Choose a reason for hiding this comment

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

Does this affect user experience at all, does it change the API?

It's encapsulated right, so almost nothing can change - fortunately - but if I didn't check this then something like Send- or Sync-ness of some types could change or something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think Send or Sync should be modified, as far as I can tell here is the only possible public APIs that might be impacted

  1. ArcArray
  2. OwnedArcRepr (which according to the code comments should never be used by the user)
/// ArcArray's representation.
///
/// *Don’t use this type directly—use the type alias
/// [`ArcArray`] for the array type!*
#[derive(Debug)]
pub struct OwnedArcRepr<A>(Arc<OwnedRepr<A>>);

ArcArray as far as I can see, never/rarely gives unfettered access to the OwnedRepr which has the Arc, as such I really don't think there is any affect to user experience, other than idiosyncratic different behavior from portable-atomic-util, which is unlikely, but possible.

@@ -45,6 +45,9 @@ matrixmultiply = { version = "0.3.2", default-features = false, features=["cgemm
serde = { version = "1.0", optional = true, default-features = false, features = ["alloc"] }
rawpointer = { version = "0.2" }

portable-atomic = { version = "1.6.0", optional = true }
portable-atomic-util = { version = "0.2.0", features = [ "alloc" ], optional = true }

Copy link
Member

Choose a reason for hiding this comment

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

Can these dependencies be automatically enabled for the relevant platform? I would feel a lot better about this, also lower complexity, if we just managed it all that way with no user visible impact, no feature enablement needed as well.

It's rare that it can be done that way, but here I think the one Arc is a drop-in for the other, and it should work well (?). Or do you see a problem with that?

And yes, it would be good to test this in CI, at least test building it.

Copy link
Member

Choose a reason for hiding this comment

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

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 issue is that the critical-section feature is recommended to be passed by the library, as mentioned by portable-atomic.

It is very strongly discouraged to enable this feature in libraries that depend on portable-atomic. The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.)

According to the Arc docs, we can detect if the target has access to Arc from the configuration flag target_has_atomic = "ptr"

Note: This type is only available on platforms that support atomic loads and stores of pointers, which includes all platforms that support the std crate but not all those which only support alloc. This may be detected at compile time using #[cfg(target_has_atomic = "ptr")].

@BjornTheProgrammer
Copy link
Contributor Author

@bluss thank you so much for the review! Don't worry about taking time, we are all busy 😅. I added the GitHub tests, but I don't have an environment to test that these are properly working, so a once-over would be much advised. Additionally I added a cfg flag to enable the dependency as suggested. I made an analysis of the user impact, and there honestly doesn't seem to be much, if any at all. However further testing should be done, just to verify that really is true.

Should I run these tests, or do you have any other suggestions/concerns?

@bluss
Copy link
Member

bluss commented Jul 31, 2024

I suggest copying this snippet from matrixmultiply and testing it like that. Just using stable, don't need any older version. (The "ensure_no_std/Cargo.toml" in this link also needs to be changed and not copied.)

https://github.com/bluss/matrixmultiply/blob/bb3dd0be9d8a9f592e567e4402950546bf710eba/.github/workflows/ci.yml#L94-L117

@BjornTheProgrammer
Copy link
Contributor Author

Changed to that! Should be fixed now.

@bluss
Copy link
Member

bluss commented Aug 1, 2024

MSRV changed to 1.64 on master. Maybe that can solve some problems (but it wasn't changed because of this PR).

@bluss bluss changed the title Made compatible with thumbv6m-none-eabi Make compatible with thumbv6m-none-eabi Aug 1, 2024
@BjornTheProgrammer
Copy link
Contributor Author

Updated to reflect the master branch with 1.64

@antimora
Copy link

antimora commented Aug 1, 2024

Burn is looking forward to this feature. It seems it's close =D

@bluss
Copy link
Member

bluss commented Aug 1, 2024

Best would be if you could squash together the changes into one commit. The merge queue preserves commits, but here we don't want to save the history. (The merge queue doesn't allow us to choose merge vs squash depending on the PR, that makes me think it's a big drawback of it.)

Cargo.toml Outdated Show resolved Hide resolved
README.rst Outdated Show resolved Hide resolved
Cargo.toml Outdated
@@ -70,8 +71,24 @@ docs = ["approx", "serde", "rayon"]
std = ["num-traits/std", "matrixmultiply/std"]
rayon = ["dep:rayon", "std"]

critical-section = ["portable-atomic/critical-section"]
Copy link
Member

Choose a reason for hiding this comment

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

is critical section the right feature name for us? Maybe not

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What would recommend the name to be? Something like no-std-enable-critical-section?

Heepless, a very popular embedded rust project names the feature portable-atomic-critical-section

# Enable polyfilling of atomics via portable-atomic, using critical section for locking
portable-atomic-critical-section = ["dep:portable-atomic", "portable-atomic", "portable-atomic?/critical-section"]

Copy link
Member

Choose a reason for hiding this comment

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

portable-atomic-critical-section sounds good then

@BjornTheProgrammer
Copy link
Contributor Author

There I think I've fixed the history, just need to rename critical-section and squash, and then we should be good. What name would you like?

@bluss bluss enabled auto-merge August 2, 2024 01:30
@bluss bluss added this pull request to the merge queue Aug 2, 2024
@BjornTheProgrammer
Copy link
Contributor Author

I've tested on actual hardware, and it seems to be working properly!

Merged via the queue into rust-ndarray:master with commit 0d3649e Aug 2, 2024
11 checks passed
@BjornTheProgrammer
Copy link
Contributor Author

@bluss I would just like to thank you very much for the time and effort you put into this. Your contributions are extremely valued. Thanks once again!

@bluss
Copy link
Member

bluss commented Aug 2, 2024

Great, I'm working on the release #1401 which is overdue (to say the least)

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