Merge pull request #6228 from scivision/scalapack

deps: add Scalapack
pull/6312/head
Jussi Pakkanen 5 years ago committed by GitHub
commit 06cc98ab54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 61
      .github/workflows/ci_frameworks.yml
  2. 39
      .github/workflows/frameworks.yml
  3. 1
      ciimage/Dockerfile
  4. 14
      docs/markdown/snippets/scalapack.md
  5. 10
      mesonbuild/dependencies/__init__.py
  6. 5
      mesonbuild/dependencies/base.py
  7. 120
      mesonbuild/dependencies/scalapack.py
  8. 2
      run_project_tests.py
  9. 220
      test cases/frameworks/30 scalapack/cmake/FindSCALAPACK.cmake
  10. 34
      test cases/frameworks/30 scalapack/main.c
  11. 25
      test cases/frameworks/30 scalapack/main.f90
  12. 27
      test cases/frameworks/30 scalapack/meson.build

@ -0,0 +1,61 @@
name: ci_frameworks
on:
push:
paths:
- "mesonbuild/dependencies/**"
- "test cases/frameworks/**"
- ".github/workflows/ci_frameworks.yml"
pull_request:
paths:
- "mesonbuild/dependencies/**"
- "test cases/frameworks/**"
- ".github/workflows/ci_frameworks.yml"
jobs:
scalapackMacOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: python -m pip install -e .
- run: brew install pkg-config ninja gcc openmpi lapack scalapack
- run: meson setup "test cases/frameworks/30 scalapack" build
- run: ninja -C build
- uses: actions/upload-artifact@v1
if: failure()
with:
name: Scalapack_Mac_build
path: build/meson-logs/meson-log.txt
- run: meson test -C build -v
- uses: actions/upload-artifact@v1
if: failure()
with:
name: Scalapack_Mac_test
path: build/meson-logs/testlog.txt
HDF5macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: python -m pip install -e .
- run: brew install pkg-config ninja gcc hdf5
- run: meson setup "test cases/frameworks/25 hdf5" build
- run: ninja -C build
- uses: actions/upload-artifact@v1
if: failure()
with:
name: HDF5_Mac_build
path: build/meson-logs/meson-log.txt
- run: meson test -C build -v
- uses: actions/upload-artifact@v1
if: failure()
with:
name: HDF5_Mac_test
path: build/meson-logs/testlog.txt

@ -1,39 +0,0 @@
# at first, we demo HDF5 framework. More can be added.
name: ci_frameworks
on:
push:
paths:
- "mesonbuild/dependencies/**"
- "test cases/frameworks/25 hdf5"
- ".github/workflows/frameworks.yml"
pull_request:
paths:
- "mesonbuild/dependencies/**"
- "test cases/frameworks/25 hdf5"
- ".github/workflows/frameworks.yml"
jobs:
macosHDF5:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: python -m pip install -e .
- run: brew install pkg-config ninja gcc hdf5
- run: meson setup "test cases/frameworks/25 hdf5" build
- run: ninja -C build
- uses: actions/upload-artifact@v1
if: failure()
with:
name: Mac_Log
path: build/meson-logs/meson-log.txt
- run: meson test -C build -v
- uses: actions/upload-artifact@v1
if: failure()
with:
name: Mac_Test
path: build/meson-logs/testlog.txt

@ -27,6 +27,7 @@ RUN sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" \
&& eatmydata apt-get -y install libboost-python-dev \
&& eatmydata apt-get -y install libblocksruntime-dev \
&& eatmydata apt-get -y install libperl-dev \
&& eatmydata apt-get -y install liblapack-dev libscalapack-mpi-dev \
&& eatmydata dub fetch urld && dub build urld --compiler=gdc \
&& eatmydata dub fetch dubtestproject \
&& eatmydata dub build dubtestproject:test1 --compiler=ldc2 \

@ -0,0 +1,14 @@
## Scalapack
added in **0.53.0**:
```meson
scalapack = dependency('scalapack')
```
Historically and through today, typical Scalapack setups have broken and incomplete pkg-config or
FindScalapack.cmake. Meson handles finding Scalapack on setups including:
* Linux: Intel MKL or OpenMPI + Netlib
* MacOS: Intel MKL or OpenMPI + Netlib
* Windows: Intel MKL (OpenMPI not available on Windows)

@ -22,6 +22,7 @@ from .base import ( # noqa: F401
from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency
from .coarrays import CoarrayDependency
from .mpi import MPIDependency
from .scalapack import ScalapackDependency
from .misc import (BlocksDependency, NetCDFDependency, OpenMPDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency, LibGCryptDependency, GpgmeDependency, ShadercDependency)
from .platform import AppleFrameworks
from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency
@ -37,11 +38,14 @@ packages.update({
'boost': BoostDependency,
'cuda': CudaDependency,
# From misc:
'blocks': BlocksDependency,
# per-file
'coarray': CoarrayDependency,
'mpi': MPIDependency,
'hdf5': HDF5Dependency,
'mpi': MPIDependency,
'scalapack': ScalapackDependency,
# From misc:
'blocks': BlocksDependency,
'netcdf': NetCDFDependency,
'openmp': OpenMPDependency,
'python3': Python3Dependency,

@ -151,7 +151,7 @@ class Dependency:
return converted
return self.compile_args
def get_link_args(self, raw=False):
def get_link_args(self, raw: bool = False) -> typing.List[str]:
if raw and self.raw_link_args is not None:
return self.raw_link_args
return self.link_args
@ -726,6 +726,9 @@ class PkgConfigDependency(ExternalDependency):
elif arg.startswith('/'):
pargs = PurePath(arg).parts
tmpl = '{}:/{}'
elif arg.startswith(('-L', '-I')) or arg[1] == ':':
# clean out improper '\\ ' as comes from some Windows pkg-config files
arg = arg.replace('\\ ', ' ')
if len(pargs) > 1 and len(pargs[1]) == 1:
arg = tmpl.format(pargs[1], '/'.join(pargs[2:]))
converted.append(arg)

@ -0,0 +1,120 @@
# Copyright 2013-2019 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pathlib import Path
import os
from .. import mesonlib
from .base import CMakeDependency, DependencyMethods, ExternalDependency, PkgConfigDependency
class ScalapackDependency(ExternalDependency):
def __init__(self, environment, kwargs: dict):
methods = mesonlib.listify(kwargs.get('method', 'auto'))
super().__init__('scalapack', environment, None, kwargs)
kwargs['required'] = False
kwargs['silent'] = True
self.is_found = False
self.static = kwargs.get('static', False)
if set(methods).intersection(['auto', 'pkg-config']):
pkgconfig_files = []
mklroot = None
is_gcc = self.clib_compiler.get_id() == 'gcc'
# Intel MKL works with non-Intel compilers too -- but not gcc on windows
if 'MKLROOT' in os.environ and not (mesonlib.is_windows() and is_gcc):
try:
mklroot = Path(os.environ['MKLROOT']).resolve()
except Exception:
pass
if mklroot is not None:
# MKL pkg-config is a start, but you have to add / change stuff
# https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool
pkgconfig_files = (
['mkl-static-lp64-iomp'] if self.static else ['mkl-dynamic-lp64-iomp']
)
if mesonlib.is_windows():
suffix = '.lib'
elif self.static:
suffix = '.a'
else:
suffix = ''
libdir = mklroot / 'lib/intel64'
# Intel compiler might not have Parallel Suite
pkgconfig_files += ['scalapack-openmpi', 'scalapack']
for pkg in pkgconfig_files:
pkgdep = PkgConfigDependency(
pkg, environment, kwargs, language=self.language
)
if pkgdep.found():
self.compile_args = pkgdep.get_compile_args()
if mklroot:
link_args = pkgdep.get_link_args()
if is_gcc:
for i, a in enumerate(link_args):
if 'mkl_intel_lp64' in a:
link_args[i] = a.replace('intel', 'gf')
break
# MKL pkg-config omits scalapack
# be sure "-L" and "-Wl" are first if present
i = 0
for j, a in enumerate(link_args):
if a.startswith(('-L', '-Wl')):
i = j + 1
elif j > 3:
break
if mesonlib.is_windows() or self.static:
link_args.insert(
i, str(libdir / ('mkl_scalapack_lp64' + suffix))
)
link_args.insert(
i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
)
else:
link_args.insert(i, '-lmkl_scalapack_lp64')
link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
else:
link_args = pkgdep.get_link_args()
self.link_args = link_args
self.version = pkgdep.get_version()
if self.version == 'unknown' and mklroot:
try:
v = (
mklroot.as_posix()
.split('compilers_and_libraries_')[1]
.split('/', 1)[0]
)
if v:
self.version = v
except IndexError:
pass
self.is_found = True
self.pcdep = pkgdep
return
if set(methods).intersection(['auto', 'cmake']):
cmakedep = CMakeDependency('Scalapack', environment, kwargs)
if cmakedep.found():
self.compile_args = cmakedep.get_compile_args()
self.link_args = cmakedep.get_link_args()
self.version = cmakedep.get_version()
self.is_found = True
return
@staticmethod
def get_methods():
return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE]

@ -544,7 +544,7 @@ def skippable(suite, test):
if test.endswith('10 gtk-doc'):
return True
# NetCDF is not in the CI image
# NetCDF is not in the CI Docker image
if test.endswith('netcdf'):
return True

@ -0,0 +1,220 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindSCALAPACK
-------------
* Michael Hirsch, Ph.D. www.scivision.dev
Let Michael know if there are more MKL / Lapack / compiler combination you want.
Refer to https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor
Finds SCALAPACK libraries for MKL, OpenMPI and MPICH.
Intel MKL relies on having environment variable MKLROOT set, typically by sourcing
mklvars.sh beforehand.
Parameters
^^^^^^^^^^
``MKL``
Intel MKL for MSVC, ICL, ICC, GCC and PGCC. Working with IntelMPI (default Window, Linux), MPICH (default Mac) or OpenMPI (Linux only).
``IntelMPI``
MKL BLACS IntelMPI
``MKL64``
MKL only: 64-bit integers (default is 32-bit integers)
``OpenMPI``
SCALAPACK + OpenMPI
``MPICH``
SCALAPACK + MPICH
Result Variables
^^^^^^^^^^^^^^^^
``SCALAPACK_FOUND``
SCALapack libraries were found
``SCALAPACK_<component>_FOUND``
SCALAPACK <component> specified was found
``SCALAPACK_LIBRARIES``
SCALapack library files
``SCALAPACK_INCLUDE_DIRS``
SCALapack include directories
References
^^^^^^^^^^
* Pkg-Config and MKL: https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool
* MKL for Windows: https://software.intel.com/en-us/mkl-windows-developer-guide-static-libraries-in-the-lib-intel64-win-directory
* MKL Windows directories: https://software.intel.com/en-us/mkl-windows-developer-guide-high-level-directory-structure
#]=======================================================================]
#===== functions
function(mkl_scala)
set(_mkl_libs ${ARGV})
foreach(s ${_mkl_libs})
find_library(SCALAPACK_${s}_LIBRARY
NAMES ${s}
PATHS ENV MKLROOT ENV I_MPI_ROOT ENV TBBROOT
PATH_SUFFIXES
lib/intel64 lib/intel64_win
intel64/lib/release
lib/intel64/gcc4.7 ../tbb/lib/intel64/gcc4.7
lib/intel64/vc_mt ../tbb/lib/intel64/vc_mt
../compiler/lib/intel64
HINTS ${MKL_LIBRARY_DIRS} ${MKL_LIBDIR}
NO_DEFAULT_PATH)
if(NOT SCALAPACK_${s}_LIBRARY)
message(WARNING "MKL component not found: " ${s})
return()
endif()
list(APPEND SCALAPACK_LIB ${SCALAPACK_${s}_LIBRARY})
endforeach()
find_path(SCALAPACK_INCLUDE_DIR
NAMES mkl_scalapack.h
PATHS ENV MKLROOT ENV I_MPI_ROOT ENV TBBROOT
PATH_SUFFIXES
include
include/intel64/${_mkl_bitflag}lp64
HINTS ${MKL_INCLUDE_DIRS})
if(NOT SCALAPACK_INCLUDE_DIR)
message(WARNING "MKL Include Dir not found")
return()
endif()
list(APPEND SCALAPACK_INCLUDE_DIR
${MKL_INCLUDE_DIRS})
set(SCALAPACK_LIBRARY ${SCALAPACK_LIB} PARENT_SCOPE)
set(SCALAPACK_INCLUDE_DIR ${SCALAPACK_INCLUDE_DIR} PARENT_SCOPE)
endfunction(mkl_scala)
#==== main program
cmake_policy(VERSION 3.11)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
cmake_policy(SET CMP0074 NEW)
cmake_policy(SET CMP0075 NEW)
endif()
if(NOT (OpenMPI IN_LIST SCALAPACK_FIND_COMPONENTS
OR MPICH IN_LIST SCALAPACK_FIND_COMPONENTS
OR MKL IN_LIST SCALAPACK_FIND_COMPONENTS))
if(DEFINED ENV{MKLROOT})
if(APPLE)
list(APPEND SCALAPACK_FIND_COMPONENTS MKL MPICH)
else()
list(APPEND SCALAPACK_FIND_COMPONENTS MKL IntelMPI)
endif()
else()
list(APPEND SCALAPACK_FIND_COMPONENTS OpenMPI)
endif()
endif()
find_package(PkgConfig)
if(NOT WIN32)
find_package(Threads) # not required--for example Flang
endif()
if(MKL IN_LIST SCALAPACK_FIND_COMPONENTS)
if(BUILD_SHARED_LIBS)
set(_mkltype dynamic)
else()
set(_mkltype static)
endif()
if(MKL64 IN_LIST SCALAPACK_FIND_COMPONENTS)
set(_mkl_bitflag i)
else()
set(_mkl_bitflag)
endif()
if(WIN32)
set(_impi impi)
else()
unset(_impi)
endif()
pkg_check_modules(MKL mkl-${_mkltype}-${_mkl_bitflag}lp64-iomp)
if(OpenMPI IN_LIST SCALAPACK_FIND_COMPONENTS)
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_openmpi_${_mkl_bitflag}lp64)
if(SCALAPACK_LIBRARY)
set(SCALAPACK_OpenMPI_FOUND true)
endif()
elseif(MPICH IN_LIST SCALAPACK_FIND_COMPONENTS)
if(APPLE)
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_mpich_${_mkl_bitflag}lp64)
elseif(WIN32)
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_mpich2_${_mkl_bitflag}lp64.lib mpi.lib fmpich2.lib)
else() # linux, yes it's just like IntelMPI
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_intelmpi_${_mkl_bitflag}lp64)
endif()
if(SCALAPACK_LIBRARY)
set(SCALAPACK_MPICH_FOUND true)
endif()
else() # IntelMPI
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_intelmpi_${_mkl_bitflag}lp64 ${_impi})
if(SCALAPACK_LIBRARY)
set(SCALAPACK_IntelMPI_FOUND true)
endif()
endif()
if(SCALAPACK_LIBRARY)
set(SCALAPACK_MKL_FOUND true)
endif()
elseif(OpenMPI IN_LIST SCALAPACK_FIND_COMPONENTS)
pkg_check_modules(SCALAPACK scalapack-openmpi)
find_library(SCALAPACK_LIBRARY
NAMES scalapack scalapack-openmpi
HINTS ${SCALAPACK_LIBRARY_DIRS} ${SCALAPACK_LIBDIR})
if(SCALAPACK_LIBRARY)
set(SCALAPACK_OpenMPI_FOUND true)
endif()
elseif(MPICH IN_LIST SCALAPACK_FIND_COMPONENTS)
find_library(SCALAPACK_LIBRARY
NAMES scalapack-mpich scalapack-mpich2)
if(SCALAPACK_LIBRARY)
set(SCALAPACK_MPICH_FOUND true)
endif()
endif()
# Finalize
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
SCALAPACK
REQUIRED_VARS SCALAPACK_LIBRARY
HANDLE_COMPONENTS)
if(SCALAPACK_FOUND)
set(SCALAPACK_LIBRARIES ${SCALAPACK_LIBRARY})
set(SCALAPACK_INCLUDE_DIRS ${SCALAPACK_INCLUDE_DIR})
endif()
mark_as_advanced(SCALAPACK_LIBRARY SCALAPACK_INCLUDE_DIR)

@ -0,0 +1,34 @@
#include <stdio.h>
// #include <mkl.h>
// #include <mkl_scalapack.h>
// #include <mkl_blacs.h>
extern float pslamch_(const int *, const char *);
extern void blacs_pinfo_(int *, int *);
extern void blacs_get_(const int *, const int *, int *);
extern void blacs_gridinit_(int *, const char *, const int *, const int *);
extern void blacs_gridinfo_(const int *, int *, int *, int *, int *);
extern void blacs_gridexit_(const int *);
extern void blacs_exit_(const int *);
int main(void){
int myid, nprocs, ictxt, mycol, myrow, npcol=2, nprow=2;
const int i0=0, i1=1, in1=-1;
blacs_pinfo_(&myid, &nprocs);
blacs_get_(&in1, &i0, &ictxt);
blacs_gridinit_(&ictxt, "C", &nprocs, &i1);
blacs_gridinfo_(&ictxt, &nprow, &npcol, &myrow, &mycol);
float eps = pslamch_(&ictxt, "E");
if (myrow == mycol) printf("OK: Scalapack C: eps= %f\n", eps);
blacs_gridexit_(&ictxt);
blacs_exit_(&i0);
return 0;
}

@ -0,0 +1,25 @@
! minimal Scalapack demo
implicit none
integer :: ictxt, myid, nprocs, mycol, myrow, npcol, nprow
real :: eps
real, external :: pslamch
! arbitrary test parameters
npcol = 2
nprow = 2
call blacs_pinfo(myid, nprocs)
call blacs_get(-1, 0, ictxt)
call blacs_gridinit(ictxt, "C", nprocs, 1)
call blacs_gridinfo(ictxt, nprow, npcol, myrow, mycol)
eps = pslamch(ictxt, 'E')
if(myrow == mycol) print '(A, F10.6)', "OK: Scalapack Fortran eps=", eps
call blacs_gridexit(ictxt)
call blacs_exit(0)
end program

@ -0,0 +1,27 @@
project('test scalapack', 'c')
mpi_c = dependency('mpi', language: 'c', required: false)
if not mpi_c.found()
error('MESON_SKIP_TEST: MPI library not available')
endif
scalapack = dependency('scalapack', required: false)
if not scalapack.found()
error('MESON_SKIP_TEST: scalapack library not available')
endif
c_exe = executable('scalapack_c', 'main.c',
dependencies: [scalapack, mpi_c])
test('scalapack_c', c_exe, timeout: 30)
if add_languages('fortran')
mpi_f = dependency('mpi', language: 'fortran', required: false)
if not mpi_f.found()
error('MESON_SKIP_TEST: MPI Fortran library not available')
endif
f_exe = executable('scalapack_fortran', 'main.f90',
dependencies: [scalapack, mpi_f])
test('scalapack_fortran', f_exe, timeout: 30)
endif
Loading…
Cancel
Save