-
Notifications
You must be signed in to change notification settings - Fork 2
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
Doctest + some SIMD BinaryOps via Eigen + compiler target architecture #16
base: main
Are you sure you want to change the base?
Conversation
Windows support msys2
FYI I ended up getting around to porting over all of the unary operators. But I will keep that separate so this PR doesn't get too big. I will hold off on opening that until we get through this one (and whatever changes are needed). If you want to see what that looks like you can see chairbender#4 . It also shows some more capabilities of doctest such as template tests to avoid duplicating lots of test logic. (And BinaryOps in chairbender#5 ) |
fantastic work, thank you for getting this rolling on both the testing and SIMD fronts! some thoughts:
ive been thinking about this and i can see the motivation behind inline tests, but i think i still fall down on the side of having them in separate files. i find this makes it easier to see whether a commit touches program code, tests or both. i havent yet asked JMC whether he would be interested in upstreaming the work in this fork, but if that happens, it seems like separated tests could help reviewability.
im not entirely sure what the Meson convention is for this kind of thing, but imo it would be nice if we could have a default build with the native flags without needing to specify a target. maybe this could be set up with
i think this is ok, and possibly alleviated by separating out the tests? |
No problem, I've moved the tests to separate files. It was admittedly kind of a hassle to have them inline and makes it harder to tell what's test code vs. production code. Especially when you start to have non-trivial test harness / test utils you want to include. I hope using extern to be able to access those ops is fine. It was proving quite difficult for me to get access to those ops through normal means, since they aren't directly exposed via the header. I updated so the default build is as you indicated. Didn't realize that param existed! I also refactored the tests based on various things I realized working on my later PRs so there is waaay less code duplication. The readme is updated to indicate you should use |
This is a more fully-fledged PR than #15 that I would intend to get merged unless there are large changes needed. Relates to #8 .
This PR:
The CI has changed slightly:
This affects the following development processes:
meson compile sapf -C build
gets you the "native" optimizations for your system). You won't be able to build all the targets.meson test unoptimized ...
. The idea being, you can build and test more quickly only by testing the unoptimized exe. Not sure if it's significant enough to be worth it.This is literally the first time I've ever had to think about compiling for specific architectures and optimization levels so there might be mistakes. I had to research a fair bit and do some trial and error to put this together. It's also the first time I've done anything with SIMD...
I wanted to submit this before porting ALL of the Accelerate code over so you can see how I'm approaching it and I can course-correct before I go too far down the wrong path. Plus there's a lot of Accelerate stuff so it should probably be split into multiple smaller PRs anyway.
Doctest Details
One (pretty minor) downside I am noticing with doctest is this: doctest/doctest#740
Basically, if we have test support stuff (like my
CHECK_ARR
), we either have to leave it in the release build, or we have to always wrap our doctests themselves PLUS the test support stuff in #ifndef DOCTEST_CONFIG_DISABLE. Because the way doctest generates the tests is such that they are reduced to "no-op" templates, but still must be able to parse. I've opted for the latter approach to minimize test code leaking into production code.Eigen / SIMD Details
I considered Eigen, SIMDe, XSIMD, and JUCE dsp library as options. Eigen seemed to be the closest to the level of abstraction that we needed (similar to Accelerate) while also having everything we need. XSIMD was the close alternative but it is more "DIY" (we were going to have to deal with alignment and simd size ourselves).
By using the
Map
type from Eigen, it reads / writes directly from / to the source array rather than having to copy / allocate into an Eigen-specific object. I'm not sure how it deals with alignment internally, but at least on the systems I've run it so far, I'm not seeing alignment assertion errors. If it does become a problem, I think we can specifically use an allocator provided by Eigen.Once you have the
Map
instance, you can perform normal operations on it (by using an Array type, they are pairwise rather than matrix / vector algebra).