Hi,

Really interesting use case!

On Fri, 13 Jun 2025 at 18:38, Timothee Mathieu <[email protected]> 
wrote:

> I finally concluded that there was a problem with AVX512 somewhere in
> the dependencies graph but I gave up identifying where, as this seems
> very complicated.

For instance, I had the question: How many packages that python-mujoco
depends on are tunable?

The answer is none. :-)

But Guix provides nice tools for manipulating all the graph.  For
example, let start an interactive session.

--8<---------------cut here---------------start------------->8---
$ cat channels.scm 
(list (channel
       (name 'guix-science)
       (url "https://codeberg.org/guix-science/guix-science.git";)
       (branch "master")
       (commit
        "8bec6b3870dd4589dc4dc7c735f7cc611ac5c947")
       (introduction
        (make-channel-introduction
         "b1fe5aaff3ab48e798a4cce02f0212bc91f423dc"
         (openpgp-fingerprint
          "CA4F 8CF4 37D7 478F DA05  5FD4 4213 7701 1A37 8446"))))
      (channel
       (name 'guix-science-nonfree)
       (url "https://codeberg.org/guix-science/guix-science-nonfree/";)
       (introduction
        (make-channel-introduction
         "58661b110325fd5d9b40e6f0177cc486a615817e"
         (openpgp-fingerprint
          "CA4F 8CF4 37D7 478F DA05  5FD4 4213 7701 1A37 8446"))))
      (channel
       (name 'guix)
       (url "https://codeberg.org/guix/guix";)
       (branch "master")
       (commit
        "6f14cf2abc6a3c3bdbf879baa0031fc236cfbe8c")
       (introduction
        (make-channel-introduction
         "9edb3f66fd807b096b48283debdcddccfea34bad"
         (openpgp-fingerprint
          "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))

$ guix time-machine -C channels.scm -- repl -L guix-rl 
--8<---------------cut here---------------end--------------->8---

>From there, it’s possible to traverse all the graph of dependencies and
collect some packages depending on a predicate (PRED) procedure.

--8<---------------cut here---------------start------------->8---
scheme@(guix-user)> (use-modules (guix)
                                 (gnu)
                                 (guix sets)
                                 (ice-9 match)
                                 (srfi srfi-1)
                                 )

(define (package-inputs* p)
  (filter-map (match-lambda
                ((_ (? package? x)) x)
                (_ #f))
              (package-inputs p)))

(define (traverse p pred)
  (let loop ((lst (list p))
             (result '())
             (visited (setq)))
    (match lst
      (()
       result)

      ((head . tail)
       (if (set-contains? visited head)
           (loop tail result visited)
           (let ((deps (append tail
                               (package-inputs* head)))
                 (res (if (pred head)
                          (cons head result)
                          result)))
             (loop deps res
                   (set-insert head visited))))))))
--8<---------------cut here---------------end--------------->8---

Then let import the package python-mujoco and check which of its
dependencies (and recursively, dependencies of dependencies, etc.) have
the property tunable?.

--8<---------------cut here---------------start------------->8---
scheme@(guix-user)> ,use(guix-rl packages mujoco)
scheme@(guix-user)>  (traverse python-mujoco
                               (lambda (p)
                                 (assq-ref (package-properties p) 'tunable?)))
$1 = ()
--8<---------------cut here---------------end--------------->8---

And none.  Well, I think it’s expected. :-)

Another example, which packages in the graph of dependencies of
python-mujoco are “replaced”, i.e., grafts.

--8<---------------cut here---------------start------------->8---
scheme@(guix-user)> ,pp (map package-full-name (traverse python-mujoco 
package-replacement))
$2 = ("[email protected]"
 "[email protected]"
 "[email protected]"
 "[email protected]")
scheme@(guix-user)> 
--8<---------------cut here---------------end--------------->8---

In the same idea, it would possible to separate packages depending on
their build system, etc.  Or using ’package-mapping‘, rewrite various
fields of some package definition.


> I guess all of this should be a cautionary tale that sometimes it may
> be needed to look carefully at the cpu flags in order to get
> reproducibility with guix shell. Ideally I think when we want to have
> something reproducible, we may want to also communicate the cpu flags
> in addition to the manifest and channels file (or at least test that
> changing the flags does not change the results).

Maybe I miss something, if I understanding correctly [1]

        The solution is to select the most appropriate implementation of
        “hot” code at run time. Video players like MPlayer and
        number-crunching software like the GNU multiprecision library
        have used this “trick” since their inception: using the cpuid
        instruction, they can determine at run time which ISA extensions
        are available and branch to routines optimized for the available
        extensions. Many other applications include similar ad-hoc
        mechanism.

Therefore, the CPU flag might be the same but not the run-time depending
on the machine where it runs.  The same binaries in the same pack
produced by Guix might use AVX when available at run-time or do not
otherwise.

Is it not what you checked when setting on and off using QEMU?

That said, yes CPU flags might change the result.  For a “trivial”
example, the C code,

        #include <stdio.h>
        #include <math.h>

        int main(){
          printf("%E\n", j0f(0x1.33d152p+1f));
        }

compiled with or without the flags ’-lm -fno-builtin’ returns,

        5.643440E-08 #  no options
        5.963430E-08 # -lm -fno-builtin

because of turning on or off constant folding compiler pass.

1: https://hpc.guix.info/blog/2018/01/pre-built-binaries-vs-performance/

>                                       It would be great if someday a
> feature to mask some CPU flag made its way to guix shell in order to
> improve reproducibility but I guess my case of having a big difference
> due to AVX512 is a limit case that does not happen often (?). 

This would mean that “guix shell” would run on the top of some emulator,
no?

Yeah I agree, it would nice to be able to launch on the fly an
environment with some specific hardware properties. :-)


Cheers,
simon

Reply via email to