3
// ************************************************************************
6
// Manycore Performance-Portable Multidimensional Arrays
8
// Copyright (2012) Sandia Corporation
10
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
11
// the U.S. Government retains certain rights in this software.
13
// Redistribution and use in source and binary forms, with or without
14
// modification, are permitted provided that the following conditions are
17
// 1. Redistributions of source code must retain the above copyright
18
// notice, this list of conditions and the following disclaimer.
20
// 2. Redistributions in binary form must reproduce the above copyright
21
// notice, this list of conditions and the following disclaimer in the
22
// documentation and/or other materials provided with the distribution.
24
// 3. Neither the name of the Corporation nor the names of the
25
// contributors may be used to endorse or promote products derived from
26
// this software without specific prior written permission.
28
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
29
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
32
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
// Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
42
// ************************************************************************
46
#include <Kokkos_Core.hpp>
47
#include <impl/Kokkos_Error.hpp>
53
//----------------------------------------------------------------------------
59
bool is_unsigned_int(const char* str)
61
const size_t len = strlen (str);
62
for (size_t i = 0; i < len; ++i) {
63
if (! isdigit (str[i])) {
70
void initialize_internal(const InitArguments& args)
72
// Protect declarations, to prevent "unused variable" warnings.
73
#if defined( KOKKOS_HAVE_OPENMP ) || defined( KOKKOS_HAVE_PTHREAD )
74
const int num_threads = args.num_threads;
75
const int use_numa = args.num_numa;
76
#endif // defined( KOKKOS_HAVE_OPENMP ) || defined( KOKKOS_HAVE_PTHREAD )
77
#if defined( KOKKOS_HAVE_CUDA )
78
const int use_gpu = args.device_id;
79
#endif // defined( KOKKOS_HAVE_CUDA )
81
#if defined( KOKKOS_HAVE_OPENMP )
82
if( Impl::is_same< Kokkos::OpenMP , Kokkos::DefaultExecutionSpace >::value ||
83
Impl::is_same< Kokkos::OpenMP , Kokkos::HostSpace::execution_space >::value ) {
86
Kokkos::OpenMP::initialize(num_threads,use_numa);
89
Kokkos::OpenMP::initialize(num_threads);
92
Kokkos::OpenMP::initialize();
94
//std::cout << "Kokkos::initialize() fyi: OpenMP enabled and initialized" << std::endl ;
97
//std::cout << "Kokkos::initialize() fyi: OpenMP enabled but not initialized" << std::endl ;
101
#if defined( KOKKOS_HAVE_PTHREAD )
102
if( Impl::is_same< Kokkos::Threads , Kokkos::DefaultExecutionSpace >::value ||
103
Impl::is_same< Kokkos::Threads , Kokkos::HostSpace::execution_space >::value ) {
106
Kokkos::Threads::initialize(num_threads,use_numa);
109
Kokkos::Threads::initialize(num_threads);
112
Kokkos::Threads::initialize();
114
//std::cout << "Kokkos::initialize() fyi: Pthread enabled and initialized" << std::endl ;
117
//std::cout << "Kokkos::initialize() fyi: Pthread enabled but not initialized" << std::endl ;
121
#if defined( KOKKOS_HAVE_SERIAL )
122
// Prevent "unused variable" warning for 'args' input struct. If
123
// Serial::initialize() ever needs to take arguments from the input
124
// struct, you may remove this line of code.
127
if( Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value ||
128
Impl::is_same< Kokkos::Serial , Kokkos::HostSpace::execution_space >::value ) {
129
Kokkos::Serial::initialize();
133
#if defined( KOKKOS_HAVE_CUDA )
134
if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value || 0 < use_gpu ) {
136
Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice( use_gpu ) );
139
Kokkos::Cuda::initialize();
141
//std::cout << "Kokkos::initialize() fyi: Cuda enabled and initialized" << std::endl ;
146
void finalize_internal( const bool all_spaces = false )
149
#if defined( KOKKOS_HAVE_CUDA )
150
if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value || all_spaces ) {
151
if(Kokkos::Cuda::is_initialized())
152
Kokkos::Cuda::finalize();
156
#if defined( KOKKOS_HAVE_OPENMP )
157
if( Impl::is_same< Kokkos::OpenMP , Kokkos::DefaultExecutionSpace >::value ||
158
Impl::is_same< Kokkos::OpenMP , Kokkos::HostSpace::execution_space >::value ||
160
if(Kokkos::OpenMP::is_initialized())
161
Kokkos::OpenMP::finalize();
165
#if defined( KOKKOS_HAVE_PTHREAD )
166
if( Impl::is_same< Kokkos::Threads , Kokkos::DefaultExecutionSpace >::value ||
167
Impl::is_same< Kokkos::Threads , Kokkos::HostSpace::execution_space >::value ||
169
if(Kokkos::Threads::is_initialized())
170
Kokkos::Threads::finalize();
174
#if defined( KOKKOS_HAVE_SERIAL )
175
if( Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value ||
176
Impl::is_same< Kokkos::Serial , Kokkos::HostSpace::execution_space >::value ||
178
if(Kokkos::Serial::is_initialized())
179
Kokkos::Serial::finalize();
185
void fence_internal()
188
#if defined( KOKKOS_HAVE_CUDA )
189
if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value ) {
190
Kokkos::Cuda::fence();
194
#if defined( KOKKOS_HAVE_OPENMP )
195
if( Impl::is_same< Kokkos::OpenMP , Kokkos::DefaultExecutionSpace >::value ||
196
Impl::is_same< Kokkos::OpenMP , Kokkos::HostSpace::execution_space >::value ) {
197
Kokkos::OpenMP::fence();
201
#if defined( KOKKOS_HAVE_PTHREAD )
202
if( Impl::is_same< Kokkos::Threads , Kokkos::DefaultExecutionSpace >::value ||
203
Impl::is_same< Kokkos::Threads , Kokkos::HostSpace::execution_space >::value ) {
204
Kokkos::Threads::fence();
208
#if defined( KOKKOS_HAVE_SERIAL )
209
if( Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value ||
210
Impl::is_same< Kokkos::Serial , Kokkos::HostSpace::execution_space >::value ) {
211
Kokkos::Serial::fence();
219
} // namespace Kokkos
221
//----------------------------------------------------------------------------
225
void initialize(int& narg, char* arg[])
227
int num_threads = -1;
231
int kokkos_threads_found = 0;
232
int kokkos_numa_found = 0;
233
int kokkos_device_found = 0;
234
int kokkos_ndevices_found = 0;
238
while (iarg < narg) {
239
if ((strncmp(arg[iarg],"--kokkos-threads",16) == 0) || (strncmp(arg[iarg],"--threads",9) == 0)) {
240
//Find the number of threads (expecting --threads=XX)
241
if (!((strncmp(arg[iarg],"--kokkos-threads=",17) == 0) || (strncmp(arg[iarg],"--threads=",10) == 0)))
242
Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--threads/--kokkos-threads'. Raised by Kokkos::initialize(int narg, char* argc[]).");
244
char* number = strchr(arg[iarg],'=')+1;
246
if(!Impl::is_unsigned_int(number) || (strlen(number)==0))
247
Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--threads/--kokkos-threads'. Raised by Kokkos::initialize(int narg, char* argc[]).");
249
if((strncmp(arg[iarg],"--kokkos-threads",16) == 0) || !kokkos_threads_found)
250
num_threads = atoi(number);
252
//Remove the --kokkos-threads argument from the list but leave --threads
253
if(strncmp(arg[iarg],"--kokkos-threads",16) == 0) {
254
for(int k=iarg;k<narg-1;k++) {
257
kokkos_threads_found=1;
262
} else if ((strncmp(arg[iarg],"--kokkos-numa",13) == 0) || (strncmp(arg[iarg],"--numa",6) == 0)) {
263
//Find the number of numa (expecting --numa=XX)
264
if (!((strncmp(arg[iarg],"--kokkos-numa=",14) == 0) || (strncmp(arg[iarg],"--numa=",7) == 0)))
265
Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--numa/--kokkos-numa'. Raised by Kokkos::initialize(int narg, char* argc[]).");
267
char* number = strchr(arg[iarg],'=')+1;
269
if(!Impl::is_unsigned_int(number) || (strlen(number)==0))
270
Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--numa/--kokkos-numa'. Raised by Kokkos::initialize(int narg, char* argc[]).");
272
if((strncmp(arg[iarg],"--kokkos-numa",13) == 0) || !kokkos_numa_found)
275
//Remove the --kokkos-numa argument from the list but leave --numa
276
if(strncmp(arg[iarg],"--kokkos-numa",13) == 0) {
277
for(int k=iarg;k<narg-1;k++) {
285
} else if ((strncmp(arg[iarg],"--kokkos-device",15) == 0) || (strncmp(arg[iarg],"--device",8) == 0)) {
286
//Find the number of device (expecting --device=XX)
287
if (!((strncmp(arg[iarg],"--kokkos-device=",16) == 0) || (strncmp(arg[iarg],"--device=",9) == 0)))
288
Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--device/--kokkos-device'. Raised by Kokkos::initialize(int narg, char* argc[]).");
290
char* number = strchr(arg[iarg],'=')+1;
292
if(!Impl::is_unsigned_int(number) || (strlen(number)==0))
293
Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--device/--kokkos-device'. Raised by Kokkos::initialize(int narg, char* argc[]).");
295
if((strncmp(arg[iarg],"--kokkos-device",15) == 0) || !kokkos_device_found)
296
device = atoi(number);
298
//Remove the --kokkos-device argument from the list but leave --device
299
if(strncmp(arg[iarg],"--kokkos-device",15) == 0) {
300
for(int k=iarg;k<narg-1;k++) {
303
kokkos_device_found=1;
308
} else if ((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || (strncmp(arg[iarg],"--ndevices",10) == 0)) {
310
//Find the number of device (expecting --device=XX)
311
if (!((strncmp(arg[iarg],"--kokkos-ndevices=",18) == 0) || (strncmp(arg[iarg],"--ndevices=",11) == 0)))
312
Impl::throw_runtime_exception("Error: expecting an '=INT[,INT]' after command line argument '--ndevices/--kokkos-ndevices'. Raised by Kokkos::initialize(int narg, char* argc[]).");
315
int skip_device = 9999;
317
char* num1 = strchr(arg[iarg],'=')+1;
318
char* num2 = strpbrk(num1,",");
319
int num1_len = num2==NULL?strlen(num1):num2-num1;
320
char* num1_only = new char[num1_len+1];
321
strncpy(num1_only,num1,num1_len);
322
num1_only[num1_len]=0;
324
if(!Impl::is_unsigned_int(num1_only) || (strlen(num1_only)==0)) {
325
Impl::throw_runtime_exception("Error: expecting an integer number after command line argument '--kokkos-ndevices'. Raised by Kokkos::initialize(int narg, char* argc[]).");
327
if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found)
328
ndevices = atoi(num1_only);
331
if(( !Impl::is_unsigned_int(num2+1) ) || (strlen(num2)==1) )
332
Impl::throw_runtime_exception("Error: expecting an integer number after command line argument '--kokkos-ndevices=XX,'. Raised by Kokkos::initialize(int narg, char* argc[]).");
334
if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found)
335
skip_device = atoi(num2+1);
338
if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found) {
340
if ((str = getenv("SLURM_LOCALID"))) {
341
int local_rank = atoi(str);
342
device = local_rank % ndevices;
343
if (device >= skip_device) device++;
345
if ((str = getenv("MV2_COMM_WORLD_LOCAL_RANK"))) {
346
int local_rank = atoi(str);
347
device = local_rank % ndevices;
348
if (device >= skip_device) device++;
350
if ((str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"))) {
351
int local_rank = atoi(str);
352
device = local_rank % ndevices;
353
if (device >= skip_device) device++;
357
if (device >= skip_device) device++;
361
//Remove the --kokkos-ndevices argument from the list but leave --ndevices
362
if(strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) {
363
for(int k=iarg;k<narg-1;k++) {
366
kokkos_ndevices_found=1;
371
} else if ((strcmp(arg[iarg],"--kokkos-help") == 0) || (strcmp(arg[iarg],"--help") == 0)) {
372
std::cout << std::endl;
373
std::cout << "--------------------------------------------------------------------------------" << std::endl;
374
std::cout << "-------------Kokkos command line arguments--------------------------------------" << std::endl;
375
std::cout << "--------------------------------------------------------------------------------" << std::endl;
376
std::cout << "The following arguments exist also without prefix 'kokkos' (e.g. --help)." << std::endl;
377
std::cout << "The prefixed arguments will be removed from the list by Kokkos::initialize()," << std::endl;
378
std::cout << "the non-prefixed ones are not removed. Prefixed versions take precedence over " << std::endl;
379
std::cout << "non prefixed ones, and the last occurence of an argument overwrites prior" << std::endl;
380
std::cout << "settings." << std::endl;
381
std::cout << std::endl;
382
std::cout << "--kokkos-help : print this message" << std::endl;
383
std::cout << "--kokkos-threads=INT : specify total number of threads or" << std::endl;
384
std::cout << " number of threads per NUMA region if " << std::endl;
385
std::cout << " used in conjunction with '--numa' option. " << std::endl;
386
std::cout << "--kokkos-numa=INT : specify number of NUMA regions used by process." << std::endl;
387
std::cout << "--kokkos-device=INT : specify device id to be used by Kokkos. " << std::endl;
388
std::cout << "--kokkos-ndevices=INT[,INT] : used when running MPI jobs. Specify number of" << std::endl;
389
std::cout << " devices per node to be used. Process to device" << std::endl;
390
std::cout << " mapping happens by obtaining the local MPI rank" << std::endl;
391
std::cout << " and assigning devices round-robin. The optional" << std::endl;
392
std::cout << " second argument allows for an existing device" << std::endl;
393
std::cout << " to be ignored. This is most useful on workstations" << std::endl;
394
std::cout << " with multiple GPUs of which one is used to drive" << std::endl;
395
std::cout << " screen output." << std::endl;
396
std::cout << std::endl;
397
std::cout << "--------------------------------------------------------------------------------" << std::endl;
398
std::cout << std::endl;
400
//Remove the --kokkos-help argument from the list but leave --ndevices
401
if(strcmp(arg[iarg],"--kokkos-help") == 0) {
402
for(int k=iarg;k<narg-1;k++) {
413
InitArguments arguments;
414
arguments.num_threads = num_threads;
415
arguments.num_numa = numa;
416
arguments.device_id = device;
417
Impl::initialize_internal(arguments);
420
void initialize(const InitArguments& arguments) {
421
Impl::initialize_internal(arguments);
426
Impl::finalize_internal();
431
enum { all_spaces = true };
432
Impl::finalize_internal( all_spaces );
437
Impl::fence_internal();
440
} // namespace Kokkos