Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions cscs-checks/prgenv/mpi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import reframe as rfm
import reframe.utility.sanity as sn


@rfm.required_version('>=2.14')
@rfm.parameterized_test(['single'], ['funneled'], ['serialized'], ['multiple'])
class MpiInitTest(rfm.RegressionTest):
"""This test checks the value returned by calling MPI_Init_thread.

Output should look the same for every prgenv (cray, gnu, intel, pgi)
(mpi_thread_multiple seems to be not supported):

# 'single':
['mpi_thread_supported=MPI_THREAD_SINGLE
mpi_thread_queried=MPI_THREAD_SINGLE 0'],

# 'funneled':
['mpi_thread_supported=MPI_THREAD_FUNNELED
mpi_thread_queried=MPI_THREAD_FUNNELED 1'],

# 'serialized':
['mpi_thread_supported=MPI_THREAD_SERIALIZED
mpi_thread_queried=MPI_THREAD_SERIALIZED 2'],

# 'multiple':
['mpi_thread_supported=MPI_THREAD_SERIALIZED
mpi_thread_queried=MPI_THREAD_SERIALIZED 2']

"""

def __init__(self, required_thread):
super().__init__()
self.valid_systems = ['daint:gpu', 'daint:mc', 'dom:gpu', 'dom:mc']
self.valid_prog_environs = ['PrgEnv-cray', 'PrgEnv-gnu',
'PrgEnv-intel', 'PrgEnv-pgi']
self.build_system = 'SingleSource'
self.sourcepath = 'mpi_init_thread.cpp'
self.cppflags = {
'single': ['-D_MPI_THREAD_SINGLE'],
'funneled': ['-D_MPI_THREAD_FUNNELED'],
'serialized': ['-D_MPI_THREAD_SERIALIZED'],
'multiple': ['-D_MPI_THREAD_MULTIPLE']
}
self.build_system.cppflags = self.cppflags[required_thread]
self.build_system.cppflags += ['-static']
self.time_limit = (0, 1, 0)
found_mpithread = sn.extractsingle(
r'^mpi_thread_required=\w+\s+mpi_thread_supported=\w+'
r'\s+mpi_thread_queried=\w+\s+(?P<result>\d)$',
self.stdout, 1, int)
self.mpithread_version = {
'single': 0,
'funneled': 1,
'serialized': 2,
'multiple': 2
}
self.sanity_patterns = sn.all([
sn.assert_found(r'tid=0 out of 1 from rank 0 out of 1',
self.stdout),
sn.assert_eq(found_mpithread,
self.mpithread_version[required_thread])
])
self.maintainers = ['JG']
self.tags = {'production'}
82 changes: 82 additions & 0 deletions cscs-checks/prgenv/src/mpi_init_thread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// testing MPI_Init_thread
#include <iostream>
#include <stdio.h>
#include <mpi.h>
using namespace std;

int main(int argc, char **argv) {
int rank, size, mpiversion, mpisubversion;
int resultlen = -1, mpi_thread_supported=-1;
char mpilibversion[MPI_MAX_LIBRARY_VERSION_STRING];

// --------------------------------------------------------------------------
// int MPI_Init_thread( int *argc, char ***argv, int required, int *provided )
//
// { MPI_THREAD_SINGLE}
// Only one thread will execute.
//
// { MPI_THREAD_FUNNELED}
// The process may be multi-threaded, but only the main thread will make MPI calls
// (all MPI calls are funneled to the main thread).
//
// { MPI_THREAD_SERIALIZED}
// The process may be multi-threaded, and multiple threads may make MPI calls, but
// only one at a time: MPI calls are not made concurrently from two distinct
// threads (all MPI calls are serialized).
//
// { MPI_THREAD_MULTIPLE}
// Multiple threads may call MPI, with no restrictions.
// --------------------------------------------------------------------------

#if defined(_MPI_THREAD_SINGLE)
cout << "mpi_thread_required=MPI_THREAD_SINGLE ";
int ev = MPI_Init_thread( 0,0, MPI_THREAD_SINGLE, &mpi_thread_supported );
#elif defined(_MPI_THREAD_FUNNELED)
cout << "mpi_thread_required=MPI_THREAD_FUNNELED ";
int ev = MPI_Init_thread( 0,0, MPI_THREAD_FUNNELED, &mpi_thread_supported );
#elif defined(_MPI_THREAD_SERIALIZED)
cout << "mpi_thread_required=MPI_THREAD_SERIALIZED ";
int ev = MPI_Init_thread( 0,0, MPI_THREAD_SERIALIZED, &mpi_thread_supported );
#elif defined(_MPI_THREAD_MULTIPLE)
cout << "mpi_thread_required=MPI_THREAD_MULTIPLE ";
int ev = MPI_Init_thread( 0,0, MPI_THREAD_MULTIPLE, &mpi_thread_supported );
#else
cout << "mpi_thread_required=none ";
int ev = MPI_Init(0,0);
#endif

switch ( mpi_thread_supported )
{
case MPI_THREAD_SINGLE: cout << "mpi_thread_supported=MPI_THREAD_SINGLE" ; break;
case MPI_THREAD_FUNNELED: cout << "mpi_thread_supported=MPI_THREAD_FUNNELED" ; break;
case MPI_THREAD_SERIALIZED: cout << "mpi_thread_supported=MPI_THREAD_SERIALIZED" ;break;
case MPI_THREAD_MULTIPLE: cout << "mpi_thread_supported=MPI_THREAD_MULTIPLE" ; break;
default: cout << "mpi_thread_supported=UNKNOWN" ;
}

// Return the level of thread support provided by the MPI library:
int mpi_thread_required=-1;
MPI_Query_thread( &mpi_thread_required );
switch ( mpi_thread_supported )
{
case MPI_THREAD_SINGLE: cout << " mpi_thread_queried=MPI_THREAD_SINGLE " << mpi_thread_required << std::endl; break;
case MPI_THREAD_FUNNELED: cout << " mpi_thread_queried=MPI_THREAD_FUNNELED " << mpi_thread_required << std::endl; break;
case MPI_THREAD_SERIALIZED: cout << " mpi_thread_queried=MPI_THREAD_SERIALIZED "<< mpi_thread_required << std::endl; break;
case MPI_THREAD_MULTIPLE: cout << " mpi_thread_queried=MPI_THREAD_MULTIPLE " << mpi_thread_required << std::endl; break;
default: cout << " mpi_thread_queried=UNKNOWN " << mpi_thread_required << std::endl;
}

MPI_Get_version( &mpiversion, &mpisubversion );
MPI_Get_library_version(mpilibversion, &resultlen);
printf( "# MPI-%d.%d = %s", mpiversion, mpisubversion, mpilibversion);

rank = MPI::COMM_WORLD.Get_rank();
size = MPI::COMM_WORLD.Get_size();
cout << "tid=0 out of 1 from rank " << rank << " out of " << size << "\n";

//std::cout << " mpi_thread_queried=" << mpi_thread_required << std::endl;

MPI::Finalize();

return 0;
} /* end func main */