Skip to content

BLD: Meson __config__ generation#22769

Merged
rgommers merged 13 commits intonumpy:mainfrom
ganesh-k13:enh_config
Jan 24, 2023
Merged

BLD: Meson __config__ generation#22769
rgommers merged 13 commits intonumpy:mainfrom
ganesh-k13:enh_config

Conversation

@ganesh-k13
Copy link
Member

@ganesh-k13 ganesh-k13 commented Dec 10, 2022

Changes

Add functionality to autogenerate build information from Meson information
In order to add new information, do the following:

  • Add the information as an argument in numpy/meson.build
  • Modify __config__.py.in to accept the new argument

New __config__.py:

'print' mode
In [2]: np.show_config()                                                                                                                                                                          
Build Dependencies:                                                                                                                                                                               
  blas:                                                                                                                                                                                           
    found: 'True'                                                                                                                                                                                 
    includedir: /usr/include/x86_64-linux-gnu/openblas-pthread/                                                                                                                                   
    libdir: /usr/lib/x86_64-linux-gnu/openblas-pthread/                                                                                                                                           
    name: openblas                                                                                                                                                                                
    openblas config: USE_64BITINT= DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 NO_CBLAS= NO_LAPACK=                                                                                                            
      NO_LAPACKE=1 NO_AFFINITY=1 USE_OPENMP=0 generic MAX_THREADS=64                                                                                                                              
    pc file directory: /usr/lib/x86_64-linux-gnu/pkgconfig
    type name: pkgconfig                                                                         
    version: 0.3.20                                                                              
  lapack:                                                                                                                                                                                         
    found: 'True'                                                                                
    includedir: /usr/include/x86_64-linux-gnu/openblas-pthread/                                  
    libdir: /usr/lib/x86_64-linux-gnu/openblas-pthread/
    name: openblas                                                                               
    openblas_config: USE_64BITINT= DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 NO_CBLAS= NO_LAPACK=           
      NO_LAPACKE=1 NO_AFFINITY=1 USE_OPENMP=0 generic MAX_THREADS=64                             
    pc file directory: /usr/lib/x86_64-linux-gnu/pkgconfig
    type_name: pkgconfig                                                                         
    version: 0.3.20                                                                              
Compilers:                                                                                                                                                                                        
  c:                                                                                             
    commands: cc                                
    linker: ld.bfd                              
    name: gcc                                   
    version: 11.3.0                                                                              
  c++:                                          
    commands: c++                               
    linker: ld.bfd                              
    name: gcc                                   
    version: 11.3.0                                                                              
  cython:                                       
    commands: cython                                                                             
    linker: cython                                                                               
    name: cython                                                                                 
    version: 0.29.30                                                                             
Machine Information:                                                                             
  build:                                                                                         
    cpu: x86_64 
    endian: little
    family: x86_64
    system: linux
  host:
    cpu: x86_64
    endian: little
    family: x86_64
    system: linux
Python Information:
  path: /home/ganesh/os/np-test/bin/python3
  version: '3.10'
'json' mode
In [3]: np.show_config(mode='json')
Out[3]: 
{'Compilers': {'c': {'name': 'gcc',
   'linker': 'ld.bfd',
   'version': '11.3.0',
   'commands': 'cc'},
  'cython': {'name': 'cython',
   'linker': 'cython',
   'version': '0.29.30',
   'commands': 'cython'},
  'c++': {'name': 'gcc',
   'linker': 'ld.bfd',
   'version': '11.3.0',
   'commands': 'c++'}},
 'Machine Information': {'host': {'cpu': 'x86_64',
   'family': 'x86_64',
   'endian': 'little',
   'system': 'linux'},
  'build': {'cpu': 'x86_64',
   'family': 'x86_64',
   'endian': 'little',
   'system': 'linux'}},
 'Build Dependencies': {'blas': {'name': 'openblas',
   'found': 'True',
   'version': '0.3.20',
   'type name': 'pkgconfig',
   'includedir': '/usr/include/x86_64-linux-gnu/openblas-pthread/',
   'libdir': '/usr/lib/x86_64-linux-gnu/openblas-pthread/',
   'openblas config': 'USE_64BITINT= DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 NO_CBLAS= NO_LAPACK= NO_LAPACKE=1 NO_AFFINITY=1 USE_OPENMP=0 generic MAX_THREADS=64',
   'pc file directory': '/usr/lib/x86_64-linux-gnu/pkgconfig'},
  'lapack': {'name': 'openblas',
   'found': 'True',
   'version': '0.3.20',
   'type_name': 'pkgconfig',
   'includedir': '/usr/include/x86_64-linux-gnu/openblas-pthread/',
   'libdir': '/usr/lib/x86_64-linux-gnu/openblas-pthread/',
   'openblas_config': 'USE_64BITINT= DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 NO_CBLAS= NO_LAPACK= NO_LAPACKE=1 NO_AFFINITY=1 USE_OPENMP=0 generic MAX_THREADS=64',
   'pc file directory': '/usr/lib/x86_64-linux-gnu/pkgconfig'}},
 'Python Information': {'path': '/home/ganesh/os/np-test/bin/python3',
  'version': '3.10'}}
'print' mode no PyYaml
In [2]: np.show_config()                                                                         
/home/ganesh/os/numpy/build-install/usr/lib/python3/dist-packages/numpy/__config__.py:117: UserWarning: Install `pyyaml` for better output                  
  warnings.warn('Install `pyyaml` for better output')           
{                                               
  "Compilers": {                                
    "c": {                                      
      "name": "gcc",                            
      "linker": "ld.bfd", 
      "version": "11.3.0",     
      "commands": "cc"                                                                           
    },                                                                                           
    "cython": {                                                                                                                                                                                   
      "name": "cython",                                                                          
      "linker": "cython",                       
      "version": "0.29.30",                     
      "commands": "cython"
    },                                                                                           
    "c++": {                                    
      "name": "gcc",                            
      "linker": "ld.bfd",                       
      "version": "11.3.0",
      "commands": "c++"                         
    }                                           
  },                                            
  "Machine Information": {
    "host": {                                   
      "cpu": "x86_64",                          
      "family": "x86_64",
      "endian": "little",
      "system": "linux"                         
    },
    "build": {
      "cpu": "x86_64",
      "family": "x86_64",
      "endian": "little",
      "system": "linux"
    }
  },
  "Build Dependencies": {
    "blas": {
      "name": "openblas",
      "found": "True",
      "version": "0.3.20",
      "type name": "pkgconfig",
      "includedir": "/usr/include/x86_64-linux-gnu/openblas-pthread/",
      "libdir": "/usr/lib/x86_64-linux-gnu/openblas-pthread/",
      "openblas config": "USE_64BITINT= DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 NO_CBLAS= NO_LAPACK= NO_LAPACKE=1 NO_AFFINITY=1 USE_OPENMP=0 generic MAX_THREADS=64",
      "pc file directory": "/usr/lib/x86_64-linux-gnu/pkgconfig"
    },
    "lapack": {
      "name": "openblas",
      "found": "True",
      "version": "0.3.20",
      "type_name": "pkgconfig",
      "includedir": "/usr/include/x86_64-linux-gnu/openblas-pthread/",
      "libdir": "/usr/lib/x86_64-linux-gnu/openblas-pthread/",
      "openblas_config": "USE_64BITINT= DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 NO_CBLAS= NO_LAPACK= NO_LAPACKE=1 NO_AFFINITY=1 USE_OPENMP=0 generic MAX_THREADS=64",
      "pc file directory": "/usr/lib/x86_64-linux-gnu/pkgconfig"
    }
  },
  "Python Information": {
    "path": "/home/ganesh/os/np-test/bin/python3",
    "version": "3.10"
  }
}

TODO

  • Remove __config__.py.in
  • Add Build Dependencies
    • BLAS
    • LAPACK
  • Add tests (surprised nothing failed after this change)
  • Add SIMD
  • Add release notes
  • Add docs

related: #20939 (comment) | scipy/scipy#16803

@ganesh-k13 ganesh-k13 requested a review from rgommers December 10, 2022 17:45
@ganesh-k13 ganesh-k13 marked this pull request as draft December 10, 2022 17:46
@ganesh-k13
Copy link
Member Author

Hi @rgommers , I've made a POC of what I had in mind and wanted to know if this is the right approach for the requirement. I can continue based on feedback.

@ganesh-k13 ganesh-k13 added component: build Meson Items related to the introduction of Meson as the new build system for NumPy labels Dec 10, 2022
@eli-schwartz
Copy link

eli-schwartz commented Dec 13, 2022

Since this only contains information known at the time of configuration, I wonder if it's necessary to have a generator script at all? Maybe passing a dict in meson to a configure_file() and using that to fill out a template, would work equally well?

The main difference is that it requires less work and one less build edge.

@ganesh-k13
Copy link
Member Author

Ah ok that makes sense. Something like this yeah?

@rgommers
Copy link
Member

Ah ok that makes sense. Something like this yeah?

That example is not the best (the if-else could use a single .set10 call instead), but the basic principle is okay for a dict passed to configure_file. In NumPy itself there's a more comprehensive example, including use of a template:

config_h = configure_file(

@ganesh-k13 ganesh-k13 force-pushed the enh_config branch 2 times, most recently from aa0a2f5 to 1a7680e Compare December 15, 2022 14:32
@rgommers
Copy link
Member

This looks pretty good at first glance @ganesh-k13. I added some comments, will do a proper review later.

"PYTHON_PATH": "@PYTHON_PATH@",
"PYTHON_VERSION": "@PYTHON_VERSION@",
},
"SIMD Extensions": {
Copy link
Member Author

Choose a reason for hiding this comment

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

As of today it's empty and get's removed by _cleanup (including the top-level key), but should work once we add SIMD. I'll keep a look out and test it post that, or I could remove it now and add it later.

@ganesh-k13
Copy link
Member Author

Are we planning on using Meson Tests? I was exploring how to add UT. If it's in the plan, I can start the test framework with this module, else I'll stick with pytest and see how to test this.

@eli-schwartz
Copy link

eli-schwartz commented Dec 16, 2022

If you've already heavily invested in pytest, meson test doesn't add much. Particularly, there's not a whole lot of benefit in taking one test harness/reporter (meson test) and using it to run another one (pytest).

You can do it, but it will just result in meson test reporting on a single test (that is, whether running pytest passes or fails) and then you can inspect the meson test logs to see the output of pytest.

It's really meant for cases where you don't have an existing test harness, and want to set one up. Particularly, when tests are run as a series of test programs rather than in-process setup/teardown.

You can use a TAP reporter for pytest, then tell meson to read the Meson Test via the TAP protocol, that does get you subtest reporting. But pytest is already pretty nice as is so it's work for no clear gain, and passing options from meson test to pytest at test time feels clunky.

Copy link
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

Hi @ganesh-k13, I did some testing. It all seems to work, my main observation is that the output is quite difficult to read. For comparison, let's have a look at show_runtime, show_config and the output of Meson itself:

In [2]: np.show_runtime()
[{'simd_extensions': {'baseline': [], 'found': [], 'not_found': []}},
 {'architecture': 'SkylakeX',
  'filepath': '/home/rgommers/mambaforge/envs/numpy-dev/lib/libopenblasp-r0.3.21.so',
  'internal_api': 'openblas',
  'num_threads': 24,
  'prefix': 'libopenblas',
  'threading_layer': 'pthreads',
  'user_api': 'blas',
  'version': '0.3.21'}]

In [3]: np.show_config()
Out[3]: 
{'C Compiler': {'C_COMP': 'gcc',
  'C_COMP_LINKER_ID': 'ld.bfd',
  'C_COMP_VERSION': '10.4.0',
...

And the Meson configure output:

C compiler for the host machine: /home/rgommers/mambaforge/envs/numpy-dev/bin/x86_64-conda-linux-gnu-cc (gcc 10.4.0 "x86_64-conda-linux-gnu-cc (conda-forge gcc 10.4.0-19) 10.4.0")
C linker for the host machine: /home/rgommers/mambaforge/envs/numpy-dev/bin/x86_64-conda-linux-gnu-cc ld.bfd 2.39
C++ compiler for the host machine: /home/rgommers/mambaforge/envs/numpy-dev/bin/x86_64-conda-linux-gnu-c++ (gcc 10.4.0 "x86_64-conda-linux-gnu-c++ (conda-forge gcc 10.4.0-19) 10.4.0")
C++ linker for the host machine: /home/rgommers/mambaforge/envs/numpy-dev/bin/x86_64-conda-linux-gnu-c++ ld.bfd 2.39
Cython compiler for the host machine: cython (cython 0.29.32)
Host machine cpu family: x86_64
Host machine cpu: x86_64
...

The capitals, hard to understand names and returning a dict of dicts instead of actually printing all contribute to the output being tricky for the reader to parse. I suggest changing the keys of the dict being as easy as possible to understand. And then also providing an option to print to stdout rather than returning a dict of dicts.

A few examples to make that concrete:

'BLAS_VERSION': '0.3.21',

I'd make that 'version': '0.3.21' (it's already under a BLAS key).

'LAPACK_TYPE_NAME': 'pkgconfig',

I'd make this: 'detection method': 'pkgconfig',

@ganesh-k13
Copy link
Member Author

Yeah, that's a really good point! In fact Matti had a similar idea in the previous PR(#20939 (comment)). I'll make those changes 👍

@ganesh-k13
Copy link
Member Author

I have added modes, please see the issue description for examples.

@ganesh-k13
Copy link
Member Author

Overall I think we can refine the keys a bit to make more sense. I'm torn between making it programmatically accessible vs human readable, for example: openblas_config vs openblas configuration. Please feel free to suggest any changes to keys or the way we are displaying them if PyYaml dump makes sense or we can write our own tabulate of sorts.

Copy link
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

This is getting close! Just a few minor comments, and docs left to be added.

@rgommers
Copy link
Member

Overall I think we can refine the keys a bit to make more sense. I'm torn between making it programmatically accessible vs human readable, for example: openblas_config vs openblas configuration.

I think optimizing for human-readable when printing sounds fine to me. I think that's the first thing people will do. Programmatic access is important too, but it's fine is that requires say a space in the key of a dict.

@ganesh-k13 ganesh-k13 force-pushed the enh_config branch 2 times, most recently from d15c981 to eaf2b21 Compare December 24, 2022 14:38
@rgommers
Copy link
Member

When you think this is ready to merge, please take it out of Draft mode and let me know - happy to get this in soon:)

@ganesh-k13
Copy link
Member Author

I didn't realise it was draft. Yeah almost ready, I'll just restrict the tests. Does it need a release note as show_config takes args now? Or we just wait for distutils to go and add one big release note?

@rgommers
Copy link
Member

distutils to go is probably ~5 months away, so let's not wait for that.

* Adds a new env in `__config__` to indicate if built with meson
@ganesh-k13 ganesh-k13 marked this pull request as ready for review December 24, 2022 16:58
@ganesh-k13 ganesh-k13 self-assigned this Dec 24, 2022
@ganesh-k13 ganesh-k13 requested a review from rgommers January 3, 2023 15:23
* Removed `Target` from host info
* Fixed warning with using compiler `path`
* Added `cross-compiled` flag
@ganesh-k13
Copy link
Member Author

Hey @rgommers , any more changes needed on this PR?

@rgommers rgommers added this to the 1.25.0 release milestone Jan 24, 2023
Copy link
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

Thanks for the ping @ganesh-k13, I missed the last update. This looks good to go now, time to merge it. Thanks a lot for getting this over the finish line!

@rgommers rgommers merged commit 04823c1 into numpy:main Jan 24, 2023
ganesh-k13 added a commit to ganesh-k13/scipy that referenced this pull request Jan 26, 2023
@seberg
Copy link
Member

seberg commented Jan 26, 2023

I am running into a circular import trying to add a flag to the main namespace. I could change that design to be a getter or move the initialization around.

But I am wondering if we can move the C imports here back to be done lazily to avoid importing C until later?

@seberg
Copy link
Member

seberg commented Jan 26, 2023

Nvm, it is nice to __cpu_baseline__ defined in that scope... Maybe this should be cleaned up, but I think the solution here is to just move my thing before this init.

@ganesh-k13
Copy link
Member Author

We could refine the cleanup to take place in the actual function and move the import inside. I think that's cleaner as well. Shall I do that? I feel we will hit this in the future.

@seberg
Copy link
Member

seberg commented Jan 26, 2023

I think it is fine as is, thanks. I had added the _utils to move most things that may be required in C into. Just now, I thought I would have this one flag directly in the main namespace, so it needs to happen before the import.

The only thing I could think of doing would be to make it a bit more obvious where the C-module is imported the first time (which is also the place guarded by this?):

    except ImportError as e:
        msg = """Error importing numpy: you should not try to import numpy from
        its source directory; please exit the numpy source tree, and relaunch
        your python interpreter from there."""
        raise ImportError(msg) from e

I think. Maybe with a comment that things that used from C must be defined before or live live in _utils/.

ganesh-k13 added a commit to ganesh-k13/scipy that referenced this pull request Jan 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: build Meson Items related to the introduction of Meson as the new build system for NumPy

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants