-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
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
WIP: python3Packages.scipy: allow overriding BLAS #230131
base: master
Are you sure you want to change the base?
Conversation
"-Csetup-args=-Dblas=cblas" | ||
"-Csetup-args=-Dlapack=lapacke" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This uses the .pc
file generated by build-support/alternatives/blas/
. I am not sure if that's what we want to use, and I'm entirely not sure when build-support/alternatives/blas
should be used.
For comparison:
❯ pkg-config mkl-dynamic-ilp64-gomp --libs
-L/nix/store/ryqzxrbdabpjxbjw97w8x6nj4fg0qhcx-mkl-2023.0.0.25398/lib -Wl,--no-as-needed -lmkl_intel_ilp64 -lmkl_gnu_thread -lmkl_core -lgomp -lpthread -lm -ldl
❯ pkg-config cblas --libs
-L/nix/store/byi7kk3jd4nblhwbzavf82pc5p4s34b1-blas-3/lib -lcblas
Note that MKL does not seem to distribute a mkl.pc
file, instead it ships:
❯ pkg-config --list-all
mkl-dynamic-ilp64-gomp mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-ilp64-tbb mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-lp64-iomp mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-lp64-seq mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-ilp64-iomp mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-ilp64-seq mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-lp64-gomp mkl - Intel(R) oneAPI Math Kernel Library
mkl-dynamic-lp64-tbb mkl - Intel(R) oneAPI Math Kernel Library
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned whether using these cblas.pc
and lapacke.pc
allows for static linkage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIU, blas.override { blasProvider = mkl; }
is somehow a way to expose mkl_rt
the "single dynamic library", and libcblas.so
in that derivation is a copy of libblas.so
from mkl
? What I do not understand if scipy is expected to link any of MKL statically, and whether the blas
switching mechanism supports static linkage.
@matthewbauer I see you worked both on blas
switching, and on blas/lapack in numpy
. Any hints?
Somewhat related: I have played with cross compiling scipy/scipy@ I haven't contributed the changes to Nixpkgs yet, because the stable scipy version is still missing some patches that will make this work, not to mention issues in Ideally, every package that depends on |
@@ -19,10 +21,15 @@ | |||
, libxcrypt | |||
}: | |||
|
|||
assert blas.provider == numpy.blas; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no asserts, because they can block overriding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assert here is to ensure that when one attempts an override they override both scipy
and numpy
. IIRC, a similar assert is used for cudaPackages
in several places, so if this change is rejected, we probably should update these as well
Previously the synchronization was achieved by putting numpy.blas
in buildInputs
. The reason I removed numpy.blas
was because numpy.blas
is blas.provider
rather than blas
. But as mentioned earlier, I'm not yet sure how to motivate the choice between blas
and blas.provider
. I'll have to inspect the history of this derivation, I guess...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assert here is to ensure that when one attempts an override they override both scipy and numpy. IIRC, a similar assert is used for cudaPackages in several places, so if this change is rejected, we probably should update these as well
The issue is explained in this older thread #36229.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't use blas.provider
when I implemented multiple blas
overrides in octave
, because there things are a little bit more complicated - the octave
expression has to coordinate between many dependencies that depend and should use the same blas
and lapack
. In this case, it's much simpler to my understanding, and I don't understand what's wrong with using numpy.blas
which points to blas.provider
. In the current state of things you can just:
scipy-myblas = super.scipy.override {
numpy = super.numpy.override {
blas = self.myblas;
};
};
Which seems very nice to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the current state of things you can just ... @doronbehar
Personally, I find this rather obscure: blas is scipy's direct dependency, but we cannot just override it, we have to override numpy instead. The actual "reason" I'm making blas
an explicit argument, however, is that from numpy.blas
(evaluates into mkl
in case of blas = prev.blas.override { blasProvider = final.mkl; }
) we cannot infer the correct pkg-config target name. With the blas-switching derivation the pkg-config target is fixed at cblas
, as far as I can tell.
The reason I put the assert
is because previously it wasn't possible to have un-synchronized numpy.blas
and scipy.blas
, but with the new interface it is and even likely to happen by accident (e.g. if one had a local override like your scipy-myblas
, then it could still evaluate, but scipy its propagated numpy would be silently using different BLAS implementations)
I see the convenience argument, but global overlays are same cost in LOC (assuming there's a binary cache), are safer, and this PR doesn't break them.
I also haven't looked into why numpy
exposes blas.provider
instead of just blas
.
Further thoughts?
@FRidh I'll switch to meta.broken
, and later open a PR to migrate cuda packages as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly!
And don't forget the self = pythonWithMyBlas;
so withPackages
functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only I think blas
and lapack
come from the outer package set (nixpkgs#blas
, not nixpkgs#python3Packages.blas
). But the idea is the same, only that it's even coarser granularity: you overlay the entire nixpkgs to achieve mutual compatibility. We can also add meta.broken = blas != numpy.blas
. I still don't see any reason we expose blas.provider
instead of blas
in numpy.passthru
, so I think we shouldn't be doing that
RE: python3.override
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
(python-final: python-prev: { ... })
];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only I think blas and lapack come from the outer package set (nixpkgs#blas, not nixpkgs#python3Packages.blas).
CallPackage should pick it up if I am correct
I still don't see any reason we expose blas.provider instead of blas in numpy.passthru, so I think we shouldn't be doing that
I don't know anymore why that was. Maybe that should be changed throughout?
Only I think
blas
andlapack
come from the outer package set (nixpkgs#blas
, notnixpkgs#python3Packages.blas
). But the idea is the same, only that it's even coarser granularity: you overlay the entire nixpkgs to achieve mutual compatibility. We can also addmeta.broken = blas != numpy.blas
. I still don't see any reason we exposeblas.provider
instead ofblas
innumpy.passthru
, so I think we shouldn't be doing thatRE:
python3.override
pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [ (python-final: python-prev: { ... }) ];
That would have an effect on the entire nixpkgs then (all interpreters + every package using any of these).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so we could just add the blas
attribute to the python package set via an overlay, is that what you're saying? And in either case it would be picked up by callPackage
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly!
pypaBuildFlags = [ | ||
# Skip sdist | ||
"--wheel" | ||
|
||
"-Csetup-args=-Dblas=cblas" | ||
"-Csetup-args=-Dlapack=lapacke" | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently, pip
now supports this as well: mesonbuild/meson-python#415 (comment)
However, we should probably finish the build
version first, and then move back to pip
, because if we're to introduce pipWheelFlags
we'll have to go through staging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This rebuild is already very large and needs to go through staging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FRidh OK, new plan then:
- drop
-m build
(because there's no need for it), - introduce
pipWheelFlags
, - expose
setupHook
inpython3Packages.meson-python
, so that includingmeson-python
innativeBuildInputs
is sufficient to build meson-python-backed packages meson-python.setupHook
looks at the same variables asmeson
, e.g.mesonFlags
meson-python.setupHook
prependsmesonFlags
with-Csetup-args=
and extendspipBuildFlags
with them
Does that sound OK? I fear this is too much indirection and could be fragile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think this is the right approach.
Note we'd want this also in the future when we would replace pip
with build
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FRidh OK, new plan then:
- drop
-m build
(because there's no need for it),- introduce
pipWheelFlags
,
I'm working on pipBuildFlags
at #239969 .
- expose
setupHook
inpython3Packages.meson-python
, so that includingmeson-python
innativeBuildInputs
is sufficient to build meson-python-backed packagesmeson-python.setupHook
looks at the same variables asmeson
, e.g.mesonFlags
meson-python.setupHook
prependsmesonFlags
with-Csetup-args=
and extendspipBuildFlags
with themDoes that sound OK? I fear this is too much indirection and could be fragile
That sounds great to me too, but what I learned from the experience in #239969 is that passing --cross-file
to meson is what's needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, does --cross-file
go into mesonFlags
(pipBuildFlags
) in addition to -Dblas...
?
BTW scipy 1.11.0 is out https://github.com/scipy/scipy/releases/tag/v1.11.0 . I plan to work on it's update, possibly along with support for cross compilation, in the upcoming week. |
Description of changes
An attempt to address #206866
Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)