easybuilders / easybuild-easyblocks

Collection of easyblocks that implement support for building and installing software with EasyBuild.
https://easybuild.io
GNU General Public License v2.0
104 stars 284 forks source link

Make OpenBLAS easyblock aware to --optarch=GENERIC #3230

Open cedricga91 opened 7 months ago

cedricga91 commented 7 months ago

Hello !

Is-it possible to make OpenBLAS easyblock aware to --optarch=GENERIC using DYNAMIC_ARCH build option (Include support for multiple CPU targets, with automatic selection at runtime).

Reference: https://fossies.org/linux/OpenBLAS/README.md

Below, a patch inspired of https://dl.rockylinux.org/vault/rocky/8.8/AppStream/source/tree/Packages/o/openblas-0.3.15-6.el8.src.rpm (only tested on x86_64) :

I have disabled DYNAMIC_OLDER build option to reduce library size.

--- openblas.py_orig    2024-02-12 14:15:58.000000000 +0100
+++ openblas.py 2024-02-25 15:49:36.413311131 +0100
@@ -10,13 +10,17 @@
 from easybuild.tools import LooseVersion
 from easybuild.easyblocks.generic.configuremake import ConfigureMake
 from easybuild.framework.easyconfig import CUSTOM
-from easybuild.tools.systemtools import POWER, get_cpu_architecture, get_shared_lib_ext
+from easybuild.tools.systemtools import X86_64, AARCH64, POWER, get_cpu_architecture, get_shared_lib_ext
 from easybuild.tools.build_log import EasyBuildError, print_warning
 from easybuild.tools.config import ERROR
 from easybuild.tools.run import run_cmd, check_log_for_errors
+from easybuild.tools.config import build_option
+from easybuild.tools.toolchain.compiler import OPTARCH_GENERIC

 LAPACK_TEST_TARGET = 'lapack-test'
 TARGET = 'TARGET'
+DYNAMIC_ARCH = 'DYNAMIC_ARCH'
+DYNAMIC_OLDER = 'DYNAMIC_OLDER'

 class EB_OpenBLAS(ConfigureMake):
@@ -59,6 +63,33 @@
             print_warning("OpenBLAS 0.3.5 and lower have known issues on POWER systems")
             default_opts[TARGET] = 'POWER8'

+        if build_option('optarch') == OPTARCH_GENERIC:
+            # if --optarch=GENERIC is used, add TARGET, DYNAMIC_ARCH and DYNAMIC_OLDER build options
+            cpu_arch = get_cpu_architecture()
+            if cpu_arch == X86_64:
+                self.cfg.update('buildopts', "%s=CORE2" % TARGET)
+                self.cfg.update('buildopts', "%s=1" % DYNAMIC_ARCH)
+                self.cfg.update('buildopts', "%s=0" % DYNAMIC_OLDER)
+            elif cpu_arch == AARCH64:
+                self.cfg.update('buildopts', "%s=ARMV8" % TARGET)
+                self.cfg.update('buildopts', "%s=1" % DYNAMIC_ARCH)
+                self.cfg.update('buildopts', "%s=0" % DYNAMIC_OLDER)
+            elif cpu_arch == POWER:
+                self.cfg.update('buildopts', "%s=POWER8" % TARGET)
+                self.cfg.update('buildopts', "%s=1" % DYNAMIC_ARCH)
+                self.cfg.update('buildopts', "%s=0" % DYNAMIC_OLDER)
+            else:
+                print_warning("Unknown CPU architecture '%s'!" % cpu_arch)
+            # Add any DYNAMIC_ARCH in buildopts to default_opts, so it is passed to testopts and installopts
+            for buildopt in self.cfg['buildopts'].split():
+                optpair = buildopt.split('=')
+                if optpair[0] == TARGET:
+                    default_opts[optpair[0]] = optpair[1]
+                if optpair[0] == DYNAMIC_ARCH:
+                    default_opts[optpair[0]] = optpair[1]
+                if optpair[0] == DYNAMIC_OLDER:
+                    default_opts[optpair[0]] = optpair[1]
+
         for key in sorted(default_opts.keys()):
             for opts_key in ['buildopts', 'testopts', 'installopts']:
                 if '%s=' % key not in self.cfg[opts_key]:

Thanks for your help ! Have a good day !

Micket commented 6 months ago

This is cool (though I really don't think i would ever use this myself, as OPTARCH_GENERIC in general for all the other packages one builds is probably pretty crappy, so just having a decent BLAS is just a small win)

My immediate thoughts is that maybe the default TARGET should be customizable. CORE2 is pretty darn old, i think maybe haswell is probably as old as people would go (though of course, OPTARCH_GENERIC target is very old) Otherwise I see no downside this allowing this option for those having to use OPTARCH_GENERIC.