PRAgMaTIc  master
PragmaticMinis.h
Go to the documentation of this file.
1 /* Copyright (C) 2010 Imperial College London and others.
2  *
3  * Please see the AUTHORS file in the main source directory for a
4  * full list of copyright holders.
5  *
6  * Gerard Gorman
7  * Applied Modelling and Computation Group
8  * Department of Earth Science and Engineering
9  * Imperial College London
10  *
11  * g.gorman@imperial.ac.uk
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above
19  * copyright notice, this list of conditions and the following
20  * disclaimer in the documentation and/or other materials provided
21  * with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
32  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
34  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #ifndef PRAGMATICMINIS_H
39 #define PRAGMATICMINIS_H
40 
41 #ifdef _OPENMP
42 #include <omp.h>
43 #endif
44 
45 #include <mpi.h>
46 
47 // Definition of size_t
48 #include <cstdlib>
49 
51 #ifdef _OPENMP
52  return omp_get_max_threads();
53 #else
54  return 1;
55 #endif
56 }
57 
59 #ifdef _OPENMP
60  return omp_get_thread_num();
61 #else
62  return 0;
63 #endif
64 }
65 
66 int pragmatic_nprocesses(MPI_Comm comm){
67  int nprocesses;
68  MPI_Comm_size(comm, &nprocesses);
69  return nprocesses;
70 }
71 
72 int pragmatic_process_id(MPI_Comm comm){
73  int id;
74  MPI_Comm_rank(comm, &id);
75  return id;
76 }
77 
78 // Returns the original value of shared, while incrementing *shared by inc.
79 size_t pragmatic_omp_atomic_capture(size_t* shared, size_t inc){
80 size_t old;
81 #if __FUJITSU
82 /*
83 * 'add' vs 'addx' --> 'addx' performs addition with carry,
84 * what we need is 'add'.
85 *
86 * 'casx' --> Register %0 is updated with the current value of the shared
87 * variable, no matter whether the comparison succeeds. Following that, it is
88 * obvious that we don't need to reload the shared variable from RAM into %g1
89 * at the next iteration of the loop, so "ldx [%1], %%g1" can be pushed
90 * outside the loop, therefore avoiding a redundant access to main memory per
91 * iteration of the loop. We just need to copy %0 to %g1.
92 *
93 * 'bne,pt' --> "pt" is a hint for the branch predictor meaning that the
94 * branch is expected NOT to be taken. The following 'mov' instruction is
95 * called "branch delayed instruction" and is executed TOGETHER with the
96 * preceeding branch instruction; we take advantage of this "instruction
97 * slot" to copy the updated value of the shared variable from %0 to %g1
98 * where it is expected to be found by the 'add'.
99 */
100 asm volatile(
101 "ldx [%1], %%g1;"
102 "retry:"
103 "add %%g1, %2, %0;"
104 "casx [%1], %%g1, %0;"
105 "cmp %0, %%g1;"
106 "bne,pn %%xcc, retry;"
107 " mov %0, %%g1;"
108 :"=&r"(old)
109 :"p"(shared), "r"(inc)
110 :"%g1"
111 );
112 #elif _OPENMP >= 201107
113 #pragma omp atomic capture
114 {
115 old = *shared;
116 *shared += inc;
117 }
118 #else
119 old = __sync_fetch_and_add(shared, inc);
120 #endif
121 return old;
122 }
123 
124 // Every element of "range" is in the form: {pair<size_t,size_t> range, int thread}
125 typedef std::pair< std::pair<size_t, size_t>, int > range_element;
127  return p1.first.first < p2.first.first;
128 }
130  return p1.first.second <= p2.first.second;
131 }
132 
133 #define pragmatic_isnormal std::isnormal
134 #define pragmatic_isnan std::isnan
135 
136 #endif
int pragmatic_process_id(MPI_Comm comm)
bool pragmatic_range_element_comparator(range_element p1, range_element p2)
int pragmatic_nthreads()
bool pragmatic_range_element_finder(range_element p1, range_element p2)
int pragmatic_thread_id()
size_t pragmatic_omp_atomic_capture(size_t *shared, size_t inc)
int pragmatic_nprocesses(MPI_Comm comm)
std::pair< std::pair< size_t, size_t >, int > range_element