Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Convert GRAS pid from long int to int; setup a virtualization layer in XBT to choose...
[simgrid.git] / include / gras / emul.h
1 /* $Id$                     */
2
3 /* gras/emul.h - public interface to emulation support                      */
4 /*                (specific parts for SG or RL)                             */
5  
6 /* Copyright (c) 2003, 2004 Martin Quinson. All rights reserved.            */
7
8 /* This program is free software; you can redistribute it and/or modify it
9  * under the terms of the license (GNU LGPL) which comes with this package. */
10
11 #ifndef GRAS_COND_H
12 #define GRAS_COND_H
13
14 #include "xbt/misc.h" /* SG_BEGIN_DECL */
15
16 SG_BEGIN_DECL()
17 XBT_PUBLIC(void) gras_global_init(int *argc, char **argv);
18 XBT_PUBLIC(void) gras_create_environment(const char *file);
19 XBT_PUBLIC(void) gras_function_register(const char *name, void* code);
20 XBT_PUBLIC(void) gras_launch_application(const char *file);
21 XBT_PUBLIC(void) gras_clean(void);
22 XBT_PUBLIC(void) gras_main(void);
23 /** @addtogroup GRAS_emul
24  *  @brief Code execution "emulation" and "virtualization".
25  * 
26  *  Emulation and virtualization words have a lot of different meanings in
27  *  computer science. Here is what we mean, and what this module allows you
28  *  to do (if it does not match your personal belives, I'm sorry):
29  * 
30  *  - Virtualization: Having some specific code for the simulation or for the reality
31  *  - Emulation: Report within the simulator the execution time of your code
32  * 
33  *  \section GRAS_emul_virtualization Virtualization 
34  * 
35  *  The whole idea of GRAS is to share the same code between the simulator
36  *  and the real implementation. But it is sometimes impossible, such as
37  *  when you want to deal with the OS. As an example, you may want to add
38  *  some extra delay before initiating a communication in RL to ensure that
39  *  the receiver is listening. This is usually useless in SG since you have
40  *  a much better control on process launch time.
41  * 
42  *  This would be done with the following snipet:
43  *  \verbatim if (gras_if_RL()) 
44    gras_os_sleep(1);\endverbatim
45  * 
46  *  Please note that those are real functions and not pre-processor
47  *  defines. This is to ensure that the same object code can be linked
48  *  against the SG library or the RL one without recompilation.
49  * 
50  *  @{
51  */
52   
53 /** \brief Returns true only if the program runs on real life */
54 XBT_PUBLIC(int) gras_if_RL(void);
55
56 /** \brief Returns true only if the program runs within the simulator */
57 XBT_PUBLIC(int) gras_if_SG(void);
58
59 /** @} */
60
61 XBT_PUBLIC(int) gras_bench_always_begin(const char *location, int line);
62 XBT_PUBLIC(int) gras_bench_always_end(void);
63 XBT_PUBLIC(int) gras_bench_once_begin(const char *location, int line);
64 XBT_PUBLIC(int) gras_bench_once_end(void);
65
66 /** @addtogroup GRAS_emul
67  *  \section GRAS_emul_timing Emulation
68  *  
69  *  For simulation accuracy, it is mandatory to report the execution time
70  *  of your code into the simulator. For example, if your application is a
71  *  parallel matrix multiplication, you naturally have to slow down the
72  *  simulated hosts actually doing the computation.
73  *  
74  *  If you know beforehands how long each task will last, simply add a call
75  *  to the gras_bench_fixed function described below. If not, you can have
76  *  GRAS benchmarking your code automatically. Simply enclose the code to
77  *  time between a macro GRAS_BENCH_*_BEGIN and GRAS_BENCH_*_END, and
78  *  you're done. There is three pair of such macros, whose characteristics
79  *  are summarized in the following table. 
80  * 
81  *  <table>
82  *   <tr>
83  *    <td><b>Name</b></td> 
84  *    <td><b>Run on host machine?</b></td>
85  *    <td><b>Benchmarked?</b></td>
86  *    <td><b>Corresponding time reported to simulation?</b></td>
87  *   </tr> 
88  *   <tr>
89  *    <td>GRAS_BENCH_ALWAYS_BEGIN()<br> 
90  *        GRAS_BENCH_ALWAYS_END()</td> 
91  *    <td>Each time</td>
92  *    <td>Each time</td>
93  *    <td>Each time</td>
94  *   </tr>
95  *   <tr>
96  *    <td>GRAS_BENCH_ONCE_RUN_ONCE_BEGIN()<br> 
97  *        GRAS_BENCH_ONCE_RUN_ONCE_END()</td>
98  *    <td>Only first time</td>
99  *    <td>Only first time</td>
100  *    <td>Each time (with stored value)</td>
101  *   </tr>
102  *   <tr>
103  *    <td>GRAS_BENCH_ONCE_RUN_ALWAYS_BEGIN()<br> 
104  *        GRAS_BENCH_ONCE_RUN_ALWAYS_END()</td>
105  *    <td>Each time</td>
106  *    <td>Only first time</td>
107  *    <td>Each time (with stored value)</td>
108  *   </tr>
109  *  </table>
110  *  
111  *  As you can see, whatever macro pair you use, the corresponding value is
112  *  repported to the simulator. After all, that's what those macro are
113  *  about ;)
114  * 
115  *  The GRAS_BENCH_ALWAYS_* macros are the simplest ones. Each time the
116  *  corresponding block is encountered, the corresponding code is executed
117  *  and timed. Then, the simulated host is given the corresponding amount
118  *  of work.
119  * 
120  *  The GRAS_BENCH_ONCE_RUN_ONCE_* macros are good for cases where you know
121  *  that your execution time is constant and where you don't care about the
122  *  result in simulation mode. In our example, each sub-block
123  *  multiplication takes exactly the same amount of work (time depends only
124  *  on size, not on content), and the operation result can safely be
125  *  ignored for algorithm result. Doing so allows you to considerably
126  *  reduce the amount of computation needed when running on simulator.
127  * 
128  *  The GRAS_BENCH_ONCE_RUN_ALWAYS_* macros are good for cases where you
129  *  know that each block will induce the same amount of work (you thus
130  *  don't want to bench it each time), but you actually need the result (so
131  *  you have to run it each time). You may ask why you don't use
132  *  GRAS_BENCH_ONCE_RUN_ONCE_* macros in this case (why you save the
133  *  benchmarking time).  The timing operation is not very intrusive by
134  *  itself, but it has to be done in an exclusive way between the several
135  *  GRAS threads (protected by mutex). So, the day where there will be
136  *  threads in GRAS, this will do a big difference. Ok, I agree. For now,
137  *  it makes no difference.
138  * 
139  *  <b>Caveats</b>
140  * 
141  *   - Blocks are automatically differenciated using the filename and line
142  *     position at which the *_BEGIN part was called. Don't put two of them
143  *     on the same line.
144  * 
145  *   - You cannot nest blocks. It would make no sense, either.
146  * 
147  *   - By the way, GRAS is not exactly designed for parallel algorithm such
148  *     as parallel matrix multiplication but for distributed ones, you weirdo.
149  *     But it's just an example ;)
150  *  
151  * @{
152  */
153 /** \brief Start benchmarking this code block
154     \hideinitializer */
155 #define GRAS_BENCH_ALWAYS_BEGIN()           gras_bench_always_begin(__FILE__, __LINE__)
156 /** \brief Stop benchmarking this code block
157     \hideinitializer */
158 #define GRAS_BENCH_ALWAYS_END()             gras_bench_always_end()
159
160 /** \brief Start benchmarking this code block if it has never been benchmarked, run it in any case
161  *  \hideinitializer */
162 #define GRAS_BENCH_ONCE_RUN_ALWAYS_BEGIN()  gras_bench_once_begin(__FILE__, __LINE__)
163 /** \brief Stop benchmarking this part of the code
164     \hideinitializer */
165 #define GRAS_BENCH_ONCE_RUN_ALWAYS_END()    gras_bench_once_end()
166
167 /** \brief Start benchmarking this code block if it has never been benchmarked, ignore it if it was
168     \hideinitializer */
169 #define GRAS_BENCH_ONCE_RUN_ONCE_BEGIN()    if (gras_bench_once_begin(__FILE__, __LINE__)) { 
170 /** \brief Stop benchmarking this part of the code
171     \hideinitializer */
172 #define GRAS_BENCH_ONCE_RUN_ONCE_END()      } gras_bench_once_end()
173 /** @} */
174
175 SG_END_DECL()
176
177 #endif /* GRAS_COND_H */
178