From 6ca4cc7e96d64e5aa2cc914b0f5d125c84fabe59 Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Wed, 24 Feb 2021 18:55:28 +0200 Subject: [PATCH 1/9] Removing test/__init__.py --- test/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/__init__.py diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29..0000000 From 908433b310c69d35281ed03c24e0595eec95396c Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Mon, 29 Mar 2021 17:15:39 +0300 Subject: [PATCH 2/9] Adding check on MPI version --- lyncs_mpi/include/pympivendor.h | 156 ++++++++++++++++++++++++++++++++ lyncs_mpi/lib.py | 32 ++++++- setup.py | 2 + 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 lyncs_mpi/include/pympivendor.h diff --git a/lyncs_mpi/include/pympivendor.h b/lyncs_mpi/include/pympivendor.h new file mode 100644 index 0000000..55812ba --- /dev/null +++ b/lyncs_mpi/include/pympivendor.h @@ -0,0 +1,156 @@ +/* SOURCE: mpi4py */ + +/* Author: Lisandro Dalcin */ +/* Contact: dalcinl@gmail.com */ + +/* Copyright (c) 2021, Lisandro Dalcin. */ +/* All rights reserved. */ + +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ + +/* * Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ + +/* * Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ + +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + +static std::string PyMPI_Get_vendor(int *version_major, + int *version_minor, + int *version_micro) +{ + const char *name = "unknown"; + int major=0, minor=0, micro=0; + +#if defined(I_MPI_VERSION) + + name = "Intel MPI"; + #if defined(I_MPI_NUMVERSION) + {int version = I_MPI_NUMVERSION/1000; + major = version/10000; version -= major*10000; + minor = version/100; version -= minor*100; + micro = version/1; version -= micro*1; } + #else + (void)sscanf(I_MPI_VERSION,"%d.%d Update %d",&major,&minor,µ); + #endif + +#elif defined(PLATFORM_MPI) + + name = "Platform MPI"; + major = (PLATFORM_MPI>>24)&0xff; + minor = (PLATFORM_MPI>>16)&0xff; + micro = (PLATFORM_MPI>> 8)&0xff; + major = (major/16)*10+(major%16); + +#elif defined(MSMPI_VER) + + name = "Microsoft MPI"; + major = MSMPI_VER >> 8; + minor = MSMPI_VER & 0xFF; + +#elif defined(MVAPICH2_VERSION) || defined(MVAPICH2_NUMVERSION) + + name = "MVAPICH2"; + #if defined(MVAPICH2_NUMVERSION) + {int version = MVAPICH2_NUMVERSION/1000; + major = version/10000; version -= major*10000; + minor = version/100; version -= minor*100; + micro = version/1; version -= micro*1; } + #elif defined(MVAPICH2_VERSION) + (void)sscanf(MVAPICH2_VERSION,"%d.%d.%d",&major,&minor,µ); + #endif + +#elif defined(MPICH_NAME) && (MPICH_NAME == 3) + + name = "MPICH"; + #if defined(MPICH_NUMVERSION) + {int version = MPICH_NUMVERSION/1000; + major = version/10000; version -= major*10000; + minor = version/100; version -= minor*100; + micro = version/1; version -= micro*1; } + #elif defined(MPICH_VERSION) + (void)sscanf(MPICH_VERSION,"%d.%d.%d",&major,&minor,µ); + #endif + +#elif defined(MPICH_NAME) && (MPICH_NAME == 2) + + name = "MPICH2"; + #if defined(MPICH2_NUMVERSION) + {int version = MPICH2_NUMVERSION/1000; + major = version/10000; version -= major*10000; + minor = version/100; version -= minor*100; + micro = version/1; version -= micro*1; } + #elif defined(MPICH2_VERSION) + (void)sscanf(MPICH2_VERSION,"%d.%d.%d",&major,&minor,µ); + #endif + +#elif defined(MPICH_NAME) && (MPICH_NAME == 1) + + name = "MPICH1"; + #if defined(MPICH_VERSION) + (void)sscanf(MPICH_VERSION,"%d.%d.%d",&major,&minor,µ); + #endif + +#elif defined(OPEN_MPI) + + name = "Open MPI"; + #if defined(OMPI_MAJOR_VERSION) + major = OMPI_MAJOR_VERSION; + #endif + #if defined(OMPI_MINOR_VERSION) + minor = OMPI_MINOR_VERSION; + #endif + #if defined(OMPI_RELEASE_VERSION) + micro = OMPI_RELEASE_VERSION; + #endif + + #if defined(OMPI_MAJOR_VERSION) + #if OMPI_MAJOR_VERSION >= 10 + name = "Spectrum MPI"; + #endif + #endif + +#elif defined(LAM_MPI) + + name = "LAM/MPI"; + #if defined(LAM_MAJOR_VERSION) + major = LAM_MAJOR_VERSION; + #endif + #if defined(LAM_MINOR_VERSION) + minor = LAM_MINOR_VERSION; + #endif + #if defined(LAM_RELEASE_VERSION) + micro = LAM_RELEASE_VERSION; + #endif + +#endif + + //if (vendor_name) *vendor_name = name; + if (version_major) *version_major = major; + if (version_minor) *version_minor = minor; + if (version_micro) *version_micro = micro; + + return name; +} + +/* + Local variables: + c-basic-offset: 2 + indent-tabs-mode: nil + End: +*/ diff --git a/lyncs_mpi/lib.py b/lyncs_mpi/lib.py index 5a72d15..c6952b7 100644 --- a/lyncs_mpi/lib.py +++ b/lyncs_mpi/lib.py @@ -9,11 +9,39 @@ from ctypes import c_int from lyncs_cppyy import Lib +from array import array +import numpy as np +from . import __path__ from .config import MPI_INCLUDE_DIRS, MPI_LIBRARIES -lib = Lib( +PATHS = list(__path__) + + +class MPILib(Lib): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + from mpi4py import MPI + + if MPI.get_vendor() != self.get_vendor(): + print("mpi4py vendor:", MPI.get_vendor()) + print("lyncs_mpi vendor:", self.get_vendor()) + raise RuntimeError( + "mpi4py and lyncs_mpi have not been compiled with the same MPI" + ) + + def get_vendor(self): + major = array("i", [0]) + minor = array("i", [0]) + micro = array("i", [0]) + name = self.PyMPI_Get_vendor(major, minor, micro) + return str(name), (major[0], minor[0], micro[0]) + + +lib = MPILib( + path=PATHS, include=MPI_INCLUDE_DIRS.split(";"), - header="mpi.h", + header=["mpi.h", "pympivendor.h"], library=MPI_LIBRARIES.split(";"), c_include=False, check="MPI_Init", diff --git a/setup.py b/setup.py index b26bf22..b33d1c1 100644 --- a/setup.py +++ b/setup.py @@ -21,4 +21,6 @@ data_files=[(".", ["config.py.in"])], install_requires=requirements, extras_require={"test": ["pytest", "pytest-cov", "pytest-benchmark"]}, + package_data={"lyncs_mpi": ["include/*.h"]}, + include_package_data=True, ) From 7cfb47d532140bf3b3fd66d5cc00ca1083ba0f20 Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Wed, 12 May 2021 12:12:30 +0300 Subject: [PATCH 3/9] Moving vendor check in load --- lyncs_mpi/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lyncs_mpi/lib.py b/lyncs_mpi/lib.py index c6952b7..ac3a2ad 100644 --- a/lyncs_mpi/lib.py +++ b/lyncs_mpi/lib.py @@ -18,8 +18,8 @@ class MPILib(Lib): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def load(self): + super().load() from mpi4py import MPI From dde5d4bafa9ade2701228c7c9eeeef77f0e46b3a Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Wed, 12 May 2021 12:15:58 +0300 Subject: [PATCH 4/9] Include headers in distribution --- setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b33d1c1..6a453b8 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,4 @@ +import glob from lyncs_setuptools import setup, CMakeExtension requirements = [ @@ -18,7 +19,10 @@ "lyncs_mpi", ext_modules=[CMakeExtension("lyncs_mpi.lib", ".")], exclude=["*.config"], - data_files=[(".", ["config.py.in"])], + data_files=[ + (".", ["config.py.in"]), + ("lyncs_mpi", glob.glob("lyncs_mpi/include/*.h")), + ], install_requires=requirements, extras_require={"test": ["pytest", "pytest-cov", "pytest-benchmark"]}, package_data={"lyncs_mpi": ["include/*.h"]}, From e5332136a334729a8a5e2997264a9cb2f284a81c Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Wed, 12 May 2021 12:17:41 +0300 Subject: [PATCH 5/9] Increasing version number --- lyncs_mpi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lyncs_mpi/__init__.py b/lyncs_mpi/__init__.py index fdb4366..5df36ef 100644 --- a/lyncs_mpi/__init__.py +++ b/lyncs_mpi/__init__.py @@ -2,7 +2,7 @@ Utils for interfacing to MPI libraries using mpi4py and dask """ -__version__ = "0.1.4" +__version__ = "0.1.5" from . import abc from .lib import * From 4b73634937a203a1a05cf1af3617bcc373d36e0b Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Wed, 12 May 2021 09:22:13 +0000 Subject: [PATCH 6/9] Updating pylint score (from Github Action) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6497cc0..84dfe7e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![license](https://img.shields.io/github/license/Lyncs-API/lyncs.mpi?logo=github&logoColor=white)](https://github.com/Lyncs-API/lyncs.mpi/blob/master/LICENSE) [![build & test](https://img.shields.io/github/workflow/status/Lyncs-API/lyncs.mpi/build%20&%20test?logo=github&logoColor=white)](https://github.com/Lyncs-API/lyncs.mpi/actions) [![codecov](https://img.shields.io/codecov/c/github/Lyncs-API/lyncs.mpi?logo=codecov&logoColor=white)](https://codecov.io/gh/Lyncs-API/lyncs.mpi) -[![pylint](https://img.shields.io/badge/pylint%20score-9.6%2F10-green?logo=python&logoColor=white)](http://pylint.pycqa.org/) +[![pylint](https://img.shields.io/badge/pylint%20score-9.5%2F10-green?logo=python&logoColor=white)](http://pylint.pycqa.org/) [![black](https://img.shields.io/badge/code%20style-black-000000.svg?logo=codefactor&logoColor=white)](https://github.com/ambv/black) This package provides tools for interfacing to MPI libraries based on `mpi4py` and `dask`: From e67c151316b3c34b038e6339e2bc505a28f7fded Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Fri, 23 Jul 2021 11:33:54 +0300 Subject: [PATCH 7/9] Adding MPI --- lyncs_mpi/lib.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lyncs_mpi/lib.py b/lyncs_mpi/lib.py index ac3a2ad..4846812 100644 --- a/lyncs_mpi/lib.py +++ b/lyncs_mpi/lib.py @@ -5,29 +5,46 @@ "default_comm", "initialized", "finalized", + "get_comm", + "MPI", ] -from ctypes import c_int -from lyncs_cppyy import Lib from array import array +from ctypes import c_int import numpy as np +from lyncs_cppyy import Lib +from lyncs_utils import static_property +from lyncs_cppyy.ll import cast from . import __path__ from .config import MPI_INCLUDE_DIRS, MPI_LIBRARIES PATHS = list(__path__) +def MPI(): + from mpi4py import MPI + + return MPI + + +def get_comm(comm): + assert isinstance(comm, MPI().Comm) + return lib.MPI_Comm(MPI()._handleof(comm)) + + class MPILib(Lib): def load(self): super().load() - from mpi4py import MPI - - if MPI.get_vendor() != self.get_vendor(): - print("mpi4py vendor:", MPI.get_vendor()) + if MPI().get_vendor() != self.get_vendor(): + print("mpi4py vendor:", MPI().get_vendor()) print("lyncs_mpi vendor:", self.get_vendor()) raise RuntimeError( - "mpi4py and lyncs_mpi have not been compiled with the same MPI" + """ + mpi4py and lyncs_mpi are not using the same MPI + Try to recompily mpi4py using: + pip install --force-reinstall --no-cache-dir mpi4py + """ ) def get_vendor(self): From 5121be55ba6221f33124bebaa56fa6e8ab8d1eb8 Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Sun, 25 Jul 2021 17:03:53 +0300 Subject: [PATCH 8/9] Using lazy_import for MPI --- lyncs_mpi/comm.py | 7 +------ lyncs_mpi/lib.py | 21 +++++++-------------- setup.py | 2 +- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lyncs_mpi/comm.py b/lyncs_mpi/comm.py index 60b2e60..7da7b70 100644 --- a/lyncs_mpi/comm.py +++ b/lyncs_mpi/comm.py @@ -7,6 +7,7 @@ from lyncs_utils import compute_property from .distributed import Distributed, results +from .lib import MPI class Comm(Distributed): @@ -22,9 +23,6 @@ def __init__(self, comms): @property def type(self): "Returns the MPI type of the class" - # pylint: disable=import-outside-toplevel - from mpi4py import MPI - return MPI.Comm @property @@ -85,9 +83,6 @@ def __init__(self, comms): @property def type(self): "Returns the MPI type of the class" - # pylint: disable=import-outside-toplevel - from mpi4py import MPI - return MPI.Cartcomm @property diff --git a/lyncs_mpi/lib.py b/lyncs_mpi/lib.py index 4846812..4b0cb7a 100644 --- a/lyncs_mpi/lib.py +++ b/lyncs_mpi/lib.py @@ -13,31 +13,26 @@ from ctypes import c_int import numpy as np from lyncs_cppyy import Lib -from lyncs_utils import static_property +from lyncs_utils import static_property, lazy_import from lyncs_cppyy.ll import cast from . import __path__ from .config import MPI_INCLUDE_DIRS, MPI_LIBRARIES PATHS = list(__path__) - - -def MPI(): - from mpi4py import MPI - - return MPI +MPI = lazy_import("mpi4py.MPI") def get_comm(comm): - assert isinstance(comm, MPI().Comm) - return lib.MPI_Comm(MPI()._handleof(comm)) + assert isinstance(comm, MPI.Comm) + return lib.MPI_Comm(MPI._handleof(comm)) class MPILib(Lib): def load(self): super().load() - if MPI().get_vendor() != self.get_vendor(): - print("mpi4py vendor:", MPI().get_vendor()) + if MPI.get_vendor() != self.get_vendor(): + print("mpi4py vendor:", MPI.get_vendor()) print("lyncs_mpi vendor:", self.get_vendor()) raise RuntimeError( """ @@ -70,11 +65,9 @@ def get_vendor(self): def default_comm(): "Returns the default communicator to be used (MPI_COMM_WORLD by default)" - # pylint: disable=import-outside-toplevel,no-name-in-module,redefined-outer-name,global-statement global COMM if not COMM: - from mpi4py.MPI import COMM_WORLD as COMM - + return MPI.COMM_WORLD return COMM diff --git a/setup.py b/setup.py index 6a453b8..15a15f2 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ "lyncs-setuptools", "mpi4py", "lyncs-cppyy", - "lyncs-utils", + "lyncs-utils>=0.2.2", "dask", "distributed", "dask[array]", From 2357de5d129deb6403a813c8727ce29a9457eb82 Mon Sep 17 00:00:00 2001 From: Simone Bacchio Date: Thu, 11 May 2023 16:22:50 +0300 Subject: [PATCH 9/9] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 84dfe7e..1c5c33e 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ pip install [--user] lyncs_mpi ## Documentation - In this package we implement several low-level tools for supporting classes distributed over MPI. These are described in this [guide]() for developers. In the following we describe the high-level tools provided in this package. @@ -110,4 +109,4 @@ where `[2,2]` are the dimensions of the multi-dimensional grid where the process Cartesian communicators directly support [Dask arrays](https://docs.dask.org/en/latest/array.html) and e.g. `cart.zeros([4,4,3,2,1])` instantiates a distributed Dask array assigned to the workers -of the communicator with local shape (chunks) `(2,2,3,2,1)`. \ No newline at end of file +of the communicator with local shape (chunks) `(2,2,3,2,1)`.