Skip to content
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

Adding vendor check #7

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)`.
of the communicator with local shape (chunks) `(2,2,3,2,1)`.
2 changes: 1 addition & 1 deletion lyncs_mpi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
7 changes: 1 addition & 6 deletions lyncs_mpi/comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from lyncs_utils import compute_property
from .distributed import Distributed, results
from .lib import MPI


class Comm(Distributed):
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
156 changes: 156 additions & 0 deletions lyncs_mpi/include/pympivendor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/* SOURCE: mpi4py */

/* Author: Lisandro Dalcin */
/* Contact: [email protected] */

/* 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,&micro);
#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,&micro);
#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,&micro);
#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,&micro);
#endif

#elif defined(MPICH_NAME) && (MPICH_NAME == 1)

name = "MPICH1";
#if defined(MPICH_VERSION)
(void)sscanf(MPICH_VERSION,"%d.%d.%d",&major,&minor,&micro);
#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:
*/
48 changes: 43 additions & 5 deletions lyncs_mpi/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,55 @@
"default_comm",
"initialized",
"finalized",
"get_comm",
"MPI",
]

from array import array
from ctypes import c_int
import numpy as np
from lyncs_cppyy import Lib
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

lib = Lib(
PATHS = list(__path__)
MPI = lazy_import("mpi4py.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()

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 are not using the same MPI
Try to recompily mpi4py using:
pip install --force-reinstall --no-cache-dir mpi4py
"""
)

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",
Expand All @@ -25,11 +65,9 @@

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


Expand Down
10 changes: 8 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import glob
from lyncs_setuptools import setup, CMakeExtension

requirements = [
"lyncs-setuptools",
"mpi4py",
"lyncs-cppyy",
"lyncs-utils",
"lyncs-utils>=0.2.2",
"dask",
"distributed",
"dask[array]",
Expand All @@ -18,7 +19,12 @@
"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"]},
include_package_data=True,
)
Empty file removed test/__init__.py
Empty file.