~ubuntu-branches/debian/sid/lammps/sid

« back to all changes in this revision

Viewing changes to lib/kokkos/core/src/impl/Kokkos_Core.cpp

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2015-04-29 23:44:49 UTC
  • mfrom: (5.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20150429234449-mbhy9utku6hp6oq8
Tags: 0~20150313.gitfa668e1-1
Upload into unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
//@HEADER
 
3
// ************************************************************************
 
4
//
 
5
//                             Kokkos
 
6
//         Manycore Performance-Portable Multidimensional Arrays
 
7
//
 
8
//              Copyright (2012) Sandia Corporation
 
9
//
 
10
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 
11
// the U.S. Government retains certain rights in this software.
 
12
//
 
13
// Redistribution and use in source and binary forms, with or without
 
14
// modification, are permitted provided that the following conditions are
 
15
// met:
 
16
//
 
17
// 1. Redistributions of source code must retain the above copyright
 
18
// notice, this list of conditions and the following disclaimer.
 
19
//
 
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.
 
23
//
 
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.
 
27
//
 
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.
 
39
//
 
40
// Questions?  Contact  H. Carter Edwards (hcedwar@sandia.gov)
 
41
//
 
42
// ************************************************************************
 
43
//@HEADER
 
44
*/
 
45
 
 
46
#include <Kokkos_Core.hpp>
 
47
#include <impl/Kokkos_Error.hpp>
 
48
#include <cctype>
 
49
#include <cstring>
 
50
#include <iostream>
 
51
#include <cstdlib>
 
52
 
 
53
//----------------------------------------------------------------------------
 
54
 
 
55
namespace Kokkos {
 
56
namespace Impl {
 
57
namespace {
 
58
 
 
59
bool is_unsigned_int(const char* str)
 
60
{
 
61
  const size_t len = strlen (str);
 
62
  for (size_t i = 0; i < len; ++i) {
 
63
    if (! isdigit (str[i])) {
 
64
      return false;
 
65
    }
 
66
  }
 
67
  return true;
 
68
}
 
69
 
 
70
void initialize_internal(const InitArguments& args)
 
71
{
 
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 )
 
80
 
 
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 ) {
 
84
    if(num_threads>0) {
 
85
      if(use_numa>0) {
 
86
        Kokkos::OpenMP::initialize(num_threads,use_numa);
 
87
      }
 
88
      else {
 
89
        Kokkos::OpenMP::initialize(num_threads);
 
90
      }
 
91
    } else {
 
92
      Kokkos::OpenMP::initialize();
 
93
    }
 
94
    //std::cout << "Kokkos::initialize() fyi: OpenMP enabled and initialized" << std::endl ;
 
95
  }
 
96
  else {
 
97
    //std::cout << "Kokkos::initialize() fyi: OpenMP enabled but not initialized" << std::endl ;
 
98
  }
 
99
#endif
 
100
 
 
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 ) {
 
104
    if(num_threads>0) {
 
105
      if(use_numa>0) {
 
106
        Kokkos::Threads::initialize(num_threads,use_numa);
 
107
      }
 
108
      else {
 
109
        Kokkos::Threads::initialize(num_threads);
 
110
      }
 
111
    } else {
 
112
      Kokkos::Threads::initialize();
 
113
    }
 
114
    //std::cout << "Kokkos::initialize() fyi: Pthread enabled and initialized" << std::endl ;
 
115
  }
 
116
  else {
 
117
    //std::cout << "Kokkos::initialize() fyi: Pthread enabled but not initialized" << std::endl ;
 
118
  }
 
119
#endif
 
120
 
 
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.
 
125
  (void) args;
 
126
 
 
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();
 
130
  }
 
131
#endif
 
132
 
 
133
#if defined( KOKKOS_HAVE_CUDA )
 
134
  if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value || 0 < use_gpu ) {
 
135
    if (use_gpu > -1) {
 
136
      Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice( use_gpu ) );
 
137
    }
 
138
    else {
 
139
      Kokkos::Cuda::initialize();
 
140
    }
 
141
    //std::cout << "Kokkos::initialize() fyi: Cuda enabled and initialized" << std::endl ;
 
142
  }
 
143
#endif
 
144
}
 
145
 
 
146
void finalize_internal( const bool all_spaces = false )
 
147
{
 
148
 
 
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();
 
153
  }
 
154
#endif
 
155
 
 
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 ||
 
159
      all_spaces ) {
 
160
    if(Kokkos::OpenMP::is_initialized())
 
161
      Kokkos::OpenMP::finalize();
 
162
  }
 
163
#endif
 
164
 
 
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 ||
 
168
      all_spaces ) {
 
169
    if(Kokkos::Threads::is_initialized())
 
170
      Kokkos::Threads::finalize();
 
171
  }
 
172
#endif
 
173
 
 
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 ||
 
177
      all_spaces ) {
 
178
    if(Kokkos::Serial::is_initialized())
 
179
      Kokkos::Serial::finalize();
 
180
  }
 
181
#endif
 
182
 
 
183
}
 
184
 
 
185
void fence_internal()
 
186
{
 
187
 
 
188
#if defined( KOKKOS_HAVE_CUDA )
 
189
  if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value ) {
 
190
    Kokkos::Cuda::fence();
 
191
  }
 
192
#endif
 
193
 
 
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();
 
198
  }
 
199
#endif
 
200
 
 
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();
 
205
  }
 
206
#endif
 
207
 
 
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();
 
212
  }
 
213
#endif
 
214
 
 
215
}
 
216
 
 
217
} // namespace
 
218
} // namespace Impl
 
219
} // namespace Kokkos
 
220
 
 
221
//----------------------------------------------------------------------------
 
222
 
 
223
namespace Kokkos {
 
224
 
 
225
void initialize(int& narg, char* arg[])
 
226
{
 
227
    int num_threads = -1;
 
228
    int numa = -1;
 
229
    int device = -1;
 
230
 
 
231
    int kokkos_threads_found = 0;
 
232
    int kokkos_numa_found = 0;
 
233
    int kokkos_device_found = 0;
 
234
    int kokkos_ndevices_found = 0;
 
235
 
 
236
    int iarg = 0;
 
237
 
 
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[]).");
 
243
 
 
244
        char* number =  strchr(arg[iarg],'=')+1;
 
245
 
 
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[]).");
 
248
 
 
249
        if((strncmp(arg[iarg],"--kokkos-threads",16) == 0) || !kokkos_threads_found)
 
250
          num_threads = atoi(number);
 
251
 
 
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++) {
 
255
            arg[k] = arg[k+1];
 
256
          }
 
257
          kokkos_threads_found=1;
 
258
          narg--;
 
259
        } else {
 
260
          iarg++;
 
261
        }
 
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[]).");
 
266
 
 
267
        char* number =  strchr(arg[iarg],'=')+1;
 
268
 
 
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[]).");
 
271
 
 
272
        if((strncmp(arg[iarg],"--kokkos-numa",13) == 0) || !kokkos_numa_found)
 
273
          numa = atoi(number);
 
274
 
 
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++) {
 
278
            arg[k] = arg[k+1];
 
279
          }
 
280
          kokkos_numa_found=1;
 
281
          narg--;
 
282
        } else {
 
283
          iarg++;
 
284
        }
 
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[]).");
 
289
 
 
290
        char* number =  strchr(arg[iarg],'=')+1;
 
291
 
 
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[]).");
 
294
 
 
295
        if((strncmp(arg[iarg],"--kokkos-device",15) == 0) || !kokkos_device_found)
 
296
          device = atoi(number);
 
297
 
 
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++) {
 
301
            arg[k] = arg[k+1];
 
302
          }
 
303
          kokkos_device_found=1;
 
304
          narg--;
 
305
        } else {
 
306
          iarg++;
 
307
        }
 
308
      } else if ((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || (strncmp(arg[iarg],"--ndevices",10) == 0)) {
 
309
 
 
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[]).");
 
313
 
 
314
        int ndevices=-1;
 
315
        int skip_device = 9999;
 
316
 
 
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;
 
323
 
 
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[]).");
 
326
        }
 
327
        if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found)
 
328
          ndevices = atoi(num1_only);
 
329
 
 
330
        if( num2 != NULL ) {
 
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[]).");
 
333
 
 
334
          if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found)
 
335
            skip_device = atoi(num2+1);
 
336
        }
 
337
 
 
338
        if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found) {
 
339
          char *str;
 
340
          if ((str = getenv("SLURM_LOCALID"))) {
 
341
            int local_rank = atoi(str);
 
342
            device = local_rank % ndevices;
 
343
            if (device >= skip_device) device++;
 
344
          }
 
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++;
 
349
          }
 
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++;
 
354
          }
 
355
          if(device==-1) {
 
356
            device = 0;
 
357
            if (device >= skip_device) device++;
 
358
          }
 
359
        }
 
360
 
 
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++) {
 
364
            arg[k] = arg[k+1];
 
365
          }
 
366
          kokkos_ndevices_found=1;
 
367
          narg--;
 
368
        } else {
 
369
          iarg++;
 
370
        }
 
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;
 
399
 
 
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++) {
 
403
             arg[k] = arg[k+1];
 
404
           }
 
405
           narg--;
 
406
         } else {
 
407
           iarg++;
 
408
         }
 
409
      } else
 
410
      iarg++;
 
411
    }
 
412
 
 
413
    InitArguments arguments;
 
414
    arguments.num_threads = num_threads;
 
415
    arguments.num_numa = numa;
 
416
    arguments.device_id = device;
 
417
    Impl::initialize_internal(arguments);
 
418
}
 
419
 
 
420
void initialize(const InitArguments& arguments) {
 
421
  Impl::initialize_internal(arguments);
 
422
}
 
423
 
 
424
void finalize()
 
425
{
 
426
  Impl::finalize_internal();
 
427
}
 
428
 
 
429
void finalize_all()
 
430
{
 
431
  enum { all_spaces = true };
 
432
  Impl::finalize_internal( all_spaces );
 
433
}
 
434
 
 
435
void fence()
 
436
{
 
437
  Impl::fence_internal();
 
438
}
 
439
 
 
440
} // namespace Kokkos
 
441