X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/aa10d062e88adc07c982d5961ecbca33972a52f8..2eb0c3e05553c3b5ffd9e2af1ba6cc3e8b1bd81b:/include/gras/emul.h diff --git a/include/gras/emul.h b/include/gras/emul.h index 054e061718..6d9b6d13d5 100644 --- a/include/gras/emul.h +++ b/include/gras/emul.h @@ -16,10 +16,31 @@ BEGIN_DECL() /** @addtogroup GRAS_emul - * @brief Handling code specific to the simulation or to the reality (Virtualization). + * @brief Code execution "emulation" and "virtualization". * - * Please note that those are real functions and not pre-processor defines. This is to ensure - * that the same object code can be linked against the SG library or the RL one without recompilation. + * Emulation and virtualization words have a lot of different meanings in + * computer science. Here is what we mean, and what this module allows you + * to do (if it does not match your personal belives, I'm sorry): + * + * - Virtualization: Having some specific code for the simulation or for the reality + * - Emulation: Report within the simulator the execution time of your code + * + * \section GRAS_emul_virtualization Virtualization + * + * The whole idea of GRAS is to share the same code between the simulator + * and the real implementation. But it is sometimes impossible, such as + * when you want to deal with the OS. As an example, you may want to add + * some extra delay before initiating a communication in RL to ensure that + * the receiver is listening. This is usually useless in SG since you have + * a much better control on process launch time. + * + * This would be done with the following snipet: + * \verbatim if (gras_if_RL()) + gras_os_sleep(1);\endverbatim + * + * Please note that those are real functions and not pre-processor + * defines. This is to ensure that the same object code can be linked + * against the SG library or the RL one without recompilation. * * @{ */ @@ -37,26 +58,114 @@ int gras_bench_always_end(void); int gras_bench_once_begin(const char *location, int line); int gras_bench_once_end(void); -/** \brief Start benchmark this part of the code +/** @addtogroup GRAS_emul + * \section GRAS_emul_timing Emulation + * + * For simulation accuracy, it is mandatory to report the execution time + * of your code into the simulator. For example, if your application is a + * parallel matrix multiplication, you naturally have to slow down the + * simulated hosts actually doing the computation. + * + * If you know beforehands how long each task will last, simply add a call + * to the gras_bench_fixed function described below. If not, you can have + * GRAS benchmarking your code automatically. Simply enclose the code to + * time between a macro GRAS_BENCH_*_BEGIN and GRAS_BENCH_*_END, and + * you're done. There is three pair of such macros, whose characteristics + * are summarized in the following table. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
NameRun on host machine?Benchmarked?Corresponding time reported to simulation?
GRAS_BENCH_ALWAYS_BEGIN()
+ * GRAS_BENCH_ALWAYS_END()
Each timeEach timeEach time
GRAS_BENCH_ONCE_RUN_ONCE_BEGIN()
+ * GRAS_BENCH_ONCE_RUN_ONCE_END()
Only first timeOnly first timeEach time (with stored value)
GRAS_BENCH_ONCE_RUN_ALWAYS_BEGIN()
+ * GRAS_BENCH_ONCE_RUN_ALWAYS_END()
Each timeOnly first timeEach time (with stored value)
+ * + * As you can see, whatever macro pair you use, the corresponding value is + * repported to the simulator. After all, that's what those macro are + * about ;) + * + * The GRAS_BENCH_ALWAYS_* macros are the simplest ones. Each time the + * corresponding block is encountered, the corresponding code is executed + * and timed. Then, the simulated host is given the corresponding amount + * of work. + * + * The GRAS_BENCH_ONCE_RUN_ONCE_* macros are good for cases where you know + * that your execution time is constant and where you don't care about the + * result in simulation mode. In our example, each sub-block + * multiplication takes exactly the same amount of work (time depends only + * on size, not on content), and the operation result can safely be + * ignored for algorithm result. Doing so allows you to considerably + * reduce the amount of computation needed when running on simulator. + * + * The GRAS_BENCH_ONCE_RUN_ALWAYS_* macros are good for cases where you + * know that each block will induce the same amount of work (you thus + * don't want to bench it each time), but you actually need the result (so + * you have to run it each time). You may ask why you don't use + * GRAS_BENCH_ONCE_RUN_ONCE_* macros in this case (why you save the + * benchmarking time). The timing operation is not very intrusive by + * itself, but it has to be done in an exclusive way between the several + * GRAS threads (protected by mutex). So, the day where there will be + * threads in GRAS, this will do a big difference. Ok, I agree. For now, + * it makes no difference. + * + * Caveats + * + * - Blocks are automatically differenciated using the filename and line + * position at which the *_BEGIN part was called. Don't put two of them + * on the same line. + * + * - You cannot nest blocks. It would make no sense, either. + * + * - By the way, GRAS is not exactly designed for parallel algorithm such + * as parallel matrix multiplication but for distributed ones, you weirdo. + * But it's just an example ;) + * + * @{ + */ +/** \brief Start benchmarking this code block \hideinitializer */ #define GRAS_BENCH_ALWAYS_BEGIN() do { if(gras_if_SG()) gras_bench_always_begin(__FILE__, __LINE__); } while(0) -/** \brief Stop benchmark this part of the code +/** \brief Stop benchmarking this code block \hideinitializer */ #define GRAS_BENCH_ALWAYS_END() do { if(gras_if_SG()) gras_bench_always_end(); } while(0) -/** \brief Start benchmark this part of the code if it has never been benchmarked before - \hideinitializer */ +/** \brief Start benchmarking this code block if it has never been benchmarked, run it in any case + * \hideinitializer */ #define GRAS_BENCH_ONCE_RUN_ALWAYS_BEGIN() do { if(gras_if_SG()) gras_bench_once_begin(__FILE__, __LINE__); } while(0) /** \brief Stop benchmarking this part of the code \hideinitializer */ #define GRAS_BENCH_ONCE_RUN_ALWAYS_END() do { if(gras_if_SG()) gras_bench_once_end(); } while(0) -/** \brief Start benchmark this part of the code if it has never been benchmarked before +/** \brief Start benchmarking this code block if it has never been benchmarked, ignore it if it was \hideinitializer */ #define GRAS_BENCH_ONCE_RUN_ONCE_BEGIN() if((gras_if_SG()&&(gras_bench_once_begin(__FILE__, __LINE__)))||(gras_if_RL())) { /** \brief Stop benchmarking this part of the code \hideinitializer */ #define GRAS_BENCH_ONCE_RUN_ONCE_END() } GRAS_BENCH_ONCE_RUN_ALWAYS_END(); +/** @} */ END_DECL()