Line data Source code
1 :
2 : /* Copyright (c) 2014, Carlos Duelo <cduelo@cesvima.upm.es>
3 : * Stefan.Eilemann@epfl.ch
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : // need to include mpi.h before stdio.h to work with Intel MPI
20 : #ifdef LUNCHBOX_USE_MPI
21 : # include <mpi.h>
22 : #endif
23 :
24 : #include "mpi.h"
25 :
26 : #include <lunchbox/log.h>
27 : #include <lunchbox/debug.h>
28 :
29 :
30 : namespace lunchbox
31 : {
32 : namespace
33 : {
34 : bool _supportsThreads = false;
35 : }
36 :
37 : namespace detail
38 : {
39 : class MPI
40 : {
41 : public:
42 2 : MPI( int* argc LB_UNUSED, char*** argv LB_UNUSED )
43 : : rank( -1 )
44 : , size( -1 )
45 2 : , initCalled( false )
46 : {
47 : #ifdef LUNCHBOX_USE_MPI
48 2 : int initialized = false;
49 2 : MPI_Initialized( &initialized );
50 2 : if( !initialized )
51 : {
52 1 : int threadLevel = -1;
53 1 : if( MPI_SUCCESS != MPI_Init_thread( argc, argv,
54 : MPI_THREAD_MULTIPLE,
55 1 : &threadLevel ))
56 : {
57 0 : LBERROR << "MPI_Init_thread failed" << std::endl;
58 2 : return;
59 : }
60 :
61 1 : initCalled = true;
62 :
63 1 : switch( threadLevel )
64 : {
65 : case MPI_THREAD_SINGLE:
66 0 : LBVERB << "MPI_THREAD_SINGLE thread support" << std::endl;
67 0 : break;
68 : case MPI_THREAD_FUNNELED:
69 0 : LBVERB << "MPI_THREAD_FUNNELED thread support" << std::endl;
70 0 : break;
71 : case MPI_THREAD_SERIALIZED:
72 1 : LBVERB << "MPI_THREAD_SERIALIZED thread support" << std::endl;
73 1 : _supportsThreads = true;
74 1 : break;
75 : case MPI_THREAD_MULTIPLE:
76 0 : LBVERB << "MPI_THREAD_MULTIPLE thread support" << std::endl;
77 0 : _supportsThreads = true;
78 0 : break;
79 : default:
80 0 : LBERROR << "Unknown MPI thread support" << std::endl;
81 : }
82 : }
83 :
84 2 : if( MPI_SUCCESS != MPI_Comm_rank( MPI_COMM_WORLD, &rank ) )
85 0 : LBERROR << "MPI_Comm_rank failed" << std::endl;
86 :
87 2 : if( MPI_SUCCESS != MPI_Comm_size( MPI_COMM_WORLD, &size ) )
88 0 : LBERROR << "MPI_Comm_size failed" << std::endl;
89 : #endif
90 : }
91 :
92 2 : ~MPI()
93 : {
94 : #ifdef LUNCHBOX_USE_MPI
95 2 : if( !initCalled )
96 1 : return;
97 :
98 1 : if( MPI_SUCCESS != MPI_Finalize() )
99 0 : LBERROR << "MPI_Finalize failed" << std::endl;
100 1 : _supportsThreads = false;
101 : #endif
102 2 : }
103 :
104 : int rank;
105 : int size;
106 : bool initCalled;
107 :
108 : };
109 : }
110 :
111 1 : MPI::MPI()
112 1 : : _impl( new detail::MPI( 0, 0 ))
113 1 : {}
114 :
115 1 : MPI::MPI( int& argc, char**& argv )
116 1 : : _impl( new detail::MPI( &argc, &argv ))
117 1 : {}
118 :
119 3 : MPI::~MPI()
120 : {
121 3 : }
122 :
123 :
124 2 : bool MPI::supportsThreads() const
125 : {
126 2 : return _supportsThreads;
127 : }
128 :
129 5 : int MPI::getRank() const
130 : {
131 5 : return _impl->rank;
132 : }
133 :
134 4 : int MPI::getSize() const
135 : {
136 4 : return _impl->size;
137 : }
138 :
139 81 : }
|