Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
authorJonathan Rouzaud-Cornabas <jonathan.rouzaud-cornabas@ens-lyon.fr>
Mon, 15 Apr 2013 16:10:51 +0000 (18:10 +0200)
committerJonathan Rouzaud-Cornabas <jonathan.rouzaud-cornabas@ens-lyon.fr>
Mon, 15 Apr 2013 16:10:51 +0000 (18:10 +0200)
180 files changed:
.gitignore
ChangeLog
README.coding
buildtools/Cmake/AddTests.cmake
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/Distrib.cmake
buildtools/Cmake/MakeLib.cmake
buildtools/Cmake/MakeLibWin.cmake
buildtools/Cmake/Option.cmake
doc/Doxyfile.in
doc/doxygen/bindings.doc
doc/doxygen/inside_extending.doc
doc/doxygen/module-msg.doc
doc/doxygen/module-smpi.doc [new file with mode: 0644]
doc/doxygen/modules.doc
examples/msg/mc/CMakeLists.txt
examples/msg/mc/bugged1.tesh
examples/msg/mc/bugged1_liveness.tesh
examples/msg/mc/chord/chord_liveness.h [deleted file]
examples/msg/mc/chord/chord_neverjoin.tesh [deleted file]
examples/msg/mc/chord_liveness/chord_liveness.c [moved from examples/msg/mc/chord/chord_liveness.c with 90% similarity]
examples/msg/mc/chord_liveness/chord_neverdeliver.tesh [new file with mode: 0644]
examples/msg/mc/chord_liveness/chord_neverjoin.tesh [new file with mode: 0644]
examples/msg/mc/chord_liveness/chord_neverjoin_timeout_visited.tesh [new file with mode: 0644]
examples/msg/mc/chord_liveness/deploy_chord_liveness.xml [moved from examples/msg/mc/chord/deploy_chord_liveness.xml with 100% similarity]
examples/msg/mc/chord_liveness/promela_chord_neverdeliver [new file with mode: 0644]
examples/msg/mc/chord_liveness/promela_chord_neverjoin [moved from examples/msg/mc/chord/promela_chord_liveness with 100% similarity]
examples/msg/mc/deploy_electric_fence.xml [moved from examples/msg/mc/deploy_random_test.xml with 71% similarity]
examples/msg/mc/electric_fence.c [new file with mode: 0644]
examples/msg/mc/random_test.c [deleted file]
examples/smpi/CMakeLists.txt
examples/smpi/MM/CMakeLists.txt
include/msg/msg.h
include/simgrid/platf.h
include/smpi/mpif.h
include/smpi/smpi.h
include/surf/simgrid_dtd.h
src/include/smpi/smpi_interface.h
src/include/surf/surfxml_parse_values.h
src/instr/instr_config.c
src/instr/instr_private.h
src/mc/mc_compare.c
src/mc/mc_dpor.c
src/mc/mc_global.c
src/mc/mc_liveness.c
src/mc/mc_request.c
src/mc/memory_map.c
src/msg/msg_mailbox.h
src/simgrid/sg_config.c
src/smpi/colls/COPYRIGHTS
src/smpi/colls/allgather-2dmesh.c [new file with mode: 0644]
src/smpi/colls/allgather-3dmesh.c [new file with mode: 0644]
src/smpi/colls/allgather-GB.c [new file with mode: 0644]
src/smpi/colls/allgather-NTSLR-NB.c [new file with mode: 0644]
src/smpi/colls/allgather-NTSLR.c [new file with mode: 0644]
src/smpi/colls/allgather-SMP-NTS.c [new file with mode: 0644]
src/smpi/colls/allgather-bruck.c [new file with mode: 0644]
src/smpi/colls/allgather-loosely-lr.c [new file with mode: 0644]
src/smpi/colls/allgather-lr.c [new file with mode: 0644]
src/smpi/colls/allgather-pair.c [new file with mode: 0644]
src/smpi/colls/allgather-rdb.c [new file with mode: 0644]
src/smpi/colls/allgather-rhv.c [new file with mode: 0644]
src/smpi/colls/allgather-ring.c [new file with mode: 0644]
src/smpi/colls/allgather-smp-simple.c [new file with mode: 0644]
src/smpi/colls/allgather-spreading-simple.c [new file with mode: 0644]
src/smpi/colls/allgatherv-GB.c [new file with mode: 0644]
src/smpi/colls/allgatherv-pair.c [new file with mode: 0644]
src/smpi/colls/allgatherv-ring.c [new file with mode: 0644]
src/smpi/colls/allreduce-NTS.c [new file with mode: 0644]
src/smpi/colls/allreduce-lr.c [new file with mode: 0644]
src/smpi/colls/allreduce-rab-rdb.c [new file with mode: 0644]
src/smpi/colls/allreduce-rab-reduce-scatter.c [new file with mode: 0644]
src/smpi/colls/allreduce-rab-rsag.c [new file with mode: 0644]
src/smpi/colls/allreduce-rab1.c [new file with mode: 0644]
src/smpi/colls/allreduce-rab2.c [new file with mode: 0644]
src/smpi/colls/allreduce-rdb.c [new file with mode: 0644]
src/smpi/colls/allreduce-redbcast.c [new file with mode: 0644]
src/smpi/colls/allreduce-smp-binomial-pipeline.c [new file with mode: 0644]
src/smpi/colls/allreduce-smp-binomial.c [new file with mode: 0644]
src/smpi/colls/allreduce-smp-rdb.c [new file with mode: 0644]
src/smpi/colls/allreduce-smp-rsag-lr.c [new file with mode: 0644]
src/smpi/colls/allreduce-smp-rsag-rab.c [new file with mode: 0644]
src/smpi/colls/allreduce-smp-rsag.c [new file with mode: 0644]
src/smpi/colls/alltoall-2dmesh.c
src/smpi/colls/alltoall-3dmesh.c
src/smpi/colls/alltoall-bruck.c
src/smpi/colls/alltoall-native.c [deleted file]
src/smpi/colls/alltoall-pair-light-barrier.c
src/smpi/colls/alltoall-pair-mpi-barrier.c
src/smpi/colls/alltoall-pair-one-barrier.c
src/smpi/colls/alltoall-pair.c
src/smpi/colls/alltoall-rdb.c
src/smpi/colls/alltoall-ring-light-barrier.c
src/smpi/colls/alltoall-ring-mpi-barrier.c
src/smpi/colls/alltoall-ring-one-barrier.c
src/smpi/colls/alltoall-ring.c
src/smpi/colls/alltoall-simple.c
src/smpi/colls/alltoallv-bruck.c [new file with mode: 0644]
src/smpi/colls/alltoallv-pair-light-barrier.c [new file with mode: 0644]
src/smpi/colls/alltoallv-pair-mpi-barrier.c [new file with mode: 0644]
src/smpi/colls/alltoallv-pair-one-barrier.c [new file with mode: 0644]
src/smpi/colls/alltoallv-pair.c [new file with mode: 0644]
src/smpi/colls/alltoallv-ring-light-barrier.c [new file with mode: 0644]
src/smpi/colls/alltoallv-ring-mpi-barrier.c [new file with mode: 0644]
src/smpi/colls/alltoallv-ring-one-barrier.c [new file with mode: 0644]
src/smpi/colls/alltoallv-ring.c [new file with mode: 0644]
src/smpi/colls/bcast-NTSB.c [new file with mode: 0644]
src/smpi/colls/bcast-NTSL-Isend.c [new file with mode: 0644]
src/smpi/colls/bcast-NTSL.c [new file with mode: 0644]
src/smpi/colls/bcast-SMP-binary.c [new file with mode: 0644]
src/smpi/colls/bcast-SMP-binomial.c [new file with mode: 0644]
src/smpi/colls/bcast-SMP-linear.c [new file with mode: 0644]
src/smpi/colls/bcast-arrival-nb.c [new file with mode: 0644]
src/smpi/colls/bcast-arrival-pattern-aware-wait.c [new file with mode: 0644]
src/smpi/colls/bcast-arrival-pattern-aware.c [new file with mode: 0644]
src/smpi/colls/bcast-arrival-scatter.c [new file with mode: 0644]
src/smpi/colls/bcast-binomial-tree.c [new file with mode: 0644]
src/smpi/colls/bcast-flattree-pipeline.c [new file with mode: 0644]
src/smpi/colls/bcast-flattree.c [new file with mode: 0644]
src/smpi/colls/bcast-scatter-LR-allgather.c [new file with mode: 0644]
src/smpi/colls/bcast-scatter-rdb-allgather.c [new file with mode: 0644]
src/smpi/colls/colls.h
src/smpi/colls/colls_global.c [new file with mode: 0644]
src/smpi/colls/colls_private.h [new file with mode: 0644]
src/smpi/colls/reduce-NTSL.c [new file with mode: 0644]
src/smpi/colls/reduce-arrival-pattern-aware.c [new file with mode: 0644]
src/smpi/colls/reduce-binomial.c [new file with mode: 0644]
src/smpi/colls/reduce-flat-tree.c [new file with mode: 0644]
src/smpi/colls/reduce-scatter-gather.c [new file with mode: 0644]
src/smpi/private.h
src/smpi/smpi_base.c
src/smpi/smpi_coll.c
src/smpi/smpi_f77.c
src/smpi/smpi_global.c
src/smpi/smpi_mpi.c
src/smpi/smpi_mpi_dt.c
src/smpi/smpi_mpi_dt_private.h
src/smpi/smpi_pmpi.c
src/smpi/smpi_replay.c
src/smpi/smpicc.in
src/smpi/smpif2c.in
src/smpi/smpif90.in
src/smpi/smpirun.in
src/surf/simgrid.dtd
src/surf/simgrid_dtd.c
src/surf/surf_routing.c
src/surf/surf_routing_cluster.c
src/surf/surf_routing_private.h
src/surf/surfxml_parse.c
src/xbt/log.c
src/xbt/mmalloc/mfree.c
src/xbt/mmalloc/mm_diff.c
src/xbt/mmalloc/mmprivate.h
src/xbt/xbt_os_time.c
teshsuite/smpi/CMakeLists.txt
teshsuite/smpi/allgather_coll.c [new file with mode: 0644]
teshsuite/smpi/allgather_coll.tesh [new file with mode: 0644]
teshsuite/smpi/allgatherv_coll.c [new file with mode: 0644]
teshsuite/smpi/allgatherv_coll.tesh [new file with mode: 0644]
teshsuite/smpi/allreduce_coll.c [new file with mode: 0644]
teshsuite/smpi/allreduce_coll.tesh [new file with mode: 0644]
teshsuite/smpi/alltoall_basic.c
teshsuite/smpi/alltoall_coll.c [new file with mode: 0644]
teshsuite/smpi/alltoall_coll.tesh [new file with mode: 0644]
teshsuite/smpi/alltoallv_coll.c [moved from teshsuite/smpi/alltoallv.c with 52% similarity]
teshsuite/smpi/alltoallv_coll.tesh [new file with mode: 0644]
teshsuite/smpi/bcast_coll.c [new file with mode: 0644]
teshsuite/smpi/bcast_coll.tesh [new file with mode: 0644]
teshsuite/smpi/mpich-test/coll/CMakeLists.txt
teshsuite/smpi/mpich-test/context/CMakeLists.txt
teshsuite/smpi/mpich-test/env/CMakeLists.txt
teshsuite/smpi/mpich-test/env/gtime.c
teshsuite/smpi/mpich-test/profile/CMakeLists.txt
teshsuite/smpi/mpich-test/pt2pt/CMakeLists.txt
teshsuite/smpi/reduce_coll.c [new file with mode: 0644]
teshsuite/smpi/reduce_coll.tesh [new file with mode: 0644]
teshsuite/xbt/mmalloc_32.tesh
teshsuite/xbt/mmalloc_64.tesh
tools/check_dist_archive.exclude
tools/tesh/run_context.c

index 47a2888..adb5d0e 100644 (file)
@@ -144,12 +144,6 @@ examples/msg/tracing/volume
 examples/msg/io/file
 examples/msg/io/file_unlink
 examples/msg/mc/bugged3
-examples/msg/mc/random_test
-examples/msg/mc/bugged1_for_liveness
-examples/msg/mc/bugged1_while_liveness
-examples/msg/mc/centralized_liveness_deadlock
-examples/msg/mc/test/test_heap_comparison
-examples/msg/mc/chord_liveness
 examples/msg/mc/test/snapshot_comparison1
 examples/msg/mc/test/snapshot_comparison2
 examples/msg/mc/test/snapshot_comparison3
index 5176313..2f30967 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,12 +12,14 @@ SimGrid (3.10) NOT RELEASED; urgency=low
    cached in the Java world
 
  SMPI:
+ * SMPI is not built as a separate library anymore, it's now included in
+   libsimgrid.
  * Improvements of the SMPI replay tool:
    - Most of the collective communications are now rooted in the same process as
      in the original application.
-   - Traces now rely on the same MPI datatype as the application (MPI_BYTE was 
+   - Traces now rely on the same MPI datatype as the application (MPI_BYTE was
      used until now). Multiple datatypes can now be used in a trace.
-   - The replay tool now supports traces produce either by TAU or a modified 
+   - The replay tool now supports traces produce either by TAU or a modified
      version of MPE.
    - Bug Fix: the compute part of the reduce action is now taken into account.
 
index e48b67f..4183390 100644 (file)
@@ -32,6 +32,16 @@ The tree is not split on projects, but on file finality:
  examples/ -> Supposed to be copy/pastable by the user, so keep it clear and
                 avoid any kind of trick. In particular, do only include the
                 public headers here.
+
+ teshsuite/ -> The more test the better. Put in there any strange test
+              doing things that the users are not supposed to do,
+              just to see if our framework is robust to incorrect and
+              unusual behaviors. All tests written in this section
+              should leverage our tesh(1) utility.
+ testsuite/ -> Old test suite, that should be converted to tesh and
+               moved to teshsuite at some point.
+
 **
 ** Indentation standard
 **
@@ -174,6 +184,9 @@ investigating the portability of the thing to windows.
       cmake -Denable_compile_optimizations=ON \
             -Denable_compile_warnings=ON
 
+* Your commit message should follow the git habits, explained eg here:
+  http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
+
 * If you want to debug memory allocation problems, here are a few hints:
   - disable compiler optimizations, to have better backtraces;
   - disable the mallocators, or it will be hard to match malloc's with
@@ -191,3 +204,4 @@ investigating the portability of the thing to windows.
   deactivate the whole logging mechanism, switching to printfs
   instead. SimGrid becomes incredibly verbose when doing so, but it
   you let you fixing the dynars.
+  
\ No newline at end of file
index 1b3dda1..55ef3ea 100644 (file)
@@ -369,6 +369,40 @@ if(NOT enable_memcheck)
       ADD_TEST(smpi-tracing-ptp                 ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cd ${CMAKE_BINARY_DIR}/examples/smpi ${CMAKE_HOME_DIRECTORY}/examples/smpi/tracing/smpi_traced.tesh)
       ADD_TEST(smpi-replay                      ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/smpi --cd ${CMAKE_BINARY_DIR}/examples/smpi ${CMAKE_HOME_DIRECTORY}/examples/smpi/replay/smpi_replay.tesh)
     endif()
+
+    FOREACH (ALLGATHER_COLL default  2dmesh 3dmesh bruck GB loosely_lr lr
+                           NTSLR NTSLR_NB pair rdb  rhv ring SMP_NTS
+                           smp_simple spreading_simple)
+        ADD_TEST(smpi-allgather-coll-${ALLGATHER_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/allgather:${ALLGATHER_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/allgather_coll.tesh)
+    ENDFOREACH()
+    FOREACH (ALLGATHERV_COLL default GB pair ring)
+        ADD_TEST(smpi-allgatherv-coll-${ALLGATHERV_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/allgatherv:${ALLGATHERV_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/allgatherv_coll.tesh)
+    ENDFOREACH()
+    FOREACH (ALLREDUCE_COLL default lr NTS rab1 rab2 rab_rdb
+                           rab_rsag rdb smp_binomial smp_binomial_pipeline
+                           smp_rdb smp_rsag smp_rsag_lr smp_rsag_rab redbcast)
+        ADD_TEST(smpi-allreduce-coll-${ALLREDUCE_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/allreduce:${ALLREDUCE_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/allreduce_coll.tesh)
+    ENDFOREACH()
+    FOREACH (ALLTOALL_COLL 2dmesh 3dmesh pair pair_one_barrier pair_light_barrier
+                          pair_mpi_barrier rdb ring ring_light_barrier
+                          ring_mpi_barrier ring_one_barrier
+                          simple bruck basic_linear)
+        ADD_TEST(smpi-alltoall-coll-${ALLTOALL_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/alltoall:${ALLTOALL_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/alltoall_coll.tesh)
+    ENDFOREACH()
+    FOREACH (ALLTOALLV_COLL default pair pair_light_barrier pair_mpi_barrier
+                           pair_one_barrier  ring ring_light_barrier
+                           ring_mpi_barrier ring_one_barrier bruck)
+        ADD_TEST(smpi-alltoallv-coll-${ALLTOALLV_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/alltoallv:${ALLTOALLV_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/alltoallv_coll.tesh)
+    ENDFOREACH()
+    FOREACH (BCAST_COLL default arrival_nb arrival_pattern_aware arrival_pattern_aware_wait arrival_scatter
+                       binomial_tree flattree flattree_pipeline NTSB NTSL NTSL_Isend scatter_LR_allgather
+                       scatter_rdb_allgather SMP_binary SMP_binomial SMP_linear)
+               ADD_TEST(smpi-bcast-coll-${BCAST_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/bcast:${BCAST_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/bcast_coll.tesh)
+    ENDFOREACH()
+    FOREACH (REDUCE_COLL default arrival_pattern_aware binomial flat_tree NTSL scatter_gather)
+        ADD_TEST(smpi-reduce-coll-${REDUCE_COLL} ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg smpi/reduce:${REDUCE_COLL} --cd ${CMAKE_BINARY_DIR}/teshsuite/smpi ${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/reduce_coll.tesh)
+    ENDFOREACH()
+
   endif()
 
   # END TESH TESTS
@@ -415,13 +449,15 @@ if(NOT enable_memcheck)
       ADD_TEST(mc-bugged1-ucontext              ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc bugged1.tesh)
       ADD_TEST(mc-centralized-ucontext          ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc centralized.tesh)
       if(PROCESSOR_x86_64) # liveness model-checking works only on 64bits (for now ...)
-        ADD_TEST(mc-bugged1-liveness-ucontext     ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc bugged1_liveness.tesh)
-        ADD_TEST(mc-chord-neverjoin-ucontext      ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/chord --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/chord chord_neverjoin.tesh)
-        ADD_TEST(mc-test-snapshot-comparison1     ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison1.tesh)
-        ADD_TEST(mc-test-snapshot-comparison2     ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison2.tesh)
-        ADD_TEST(mc-test-snapshot-comparison3     ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison3.tesh)
-        ADD_TEST(mc-test-snapshot-comparison4     ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison4.tesh)
-        ADD_TEST(mc-test-snapshot-comparison5     ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison5.tesh)
+        ADD_TEST(mc-bugged1-liveness-ucontext                  ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc bugged1_liveness.tesh)
+        ADD_TEST(mc-chord-neverjoin-ucontext                   ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/chord_liveness --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/chord_liveness chord_neverjoin.tesh)
+        ADD_TEST(mc-chord-neverdeliver-ucontext                ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/chord_liveness --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/chord_liveness chord_neverdeliver.tesh)
+        ADD_TEST(mc-chord-neverjoin-timeout-visited-ucontext   ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/chord_liveness --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/chord_liveness chord_neverjoin_timeout_visited.tesh)
+        ADD_TEST(mc-test-snapshot-comparison1                  ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison1.tesh)
+        ADD_TEST(mc-test-snapshot-comparison2                  ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison2.tesh)
+        ADD_TEST(mc-test-snapshot-comparison3                  ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison3.tesh)
+        ADD_TEST(mc-test-snapshot-comparison4                  ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison4.tesh)
+        ADD_TEST(mc-test-snapshot-comparison5                  ${CMAKE_BINARY_DIR}/bin/tesh ${TESH_OPTION} --cfg contexts/factory:ucontext --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/mc/test --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/mc/test snapshot_comparison5.tesh)
       endif()
     endif()
     if(HAVE_RAWCTX)
index 0cf83fa..3e9cb61 100644 (file)
@@ -35,7 +35,9 @@ set(EXTRA_DIST
   src/simix/smx_smurf_private.h
   src/simix/smx_synchro_private.h
   src/smpi/README
+  src/smpi/colls/COPYRIGHTS
   src/smpi/colls/colls.h
+  src/smpi/colls/colls_private.h
   src/smpi/private.h
   src/smpi/smpi_mpi_dt_private.h
   src/surf/cpu_ti_private.h
@@ -108,9 +110,43 @@ set(SMPI_SRC
   src/smpi/smpi_mpi_dt.c
   src/smpi/smpi_pmpi.c
   src/smpi/smpi_replay.c
+  src/smpi/colls/colls_global.c
+  src/smpi/colls/allgather-2dmesh.c
+  src/smpi/colls/allgather-3dmesh.c
+  src/smpi/colls/allgather-bruck.c
+  src/smpi/colls/allgather-GB.c
+  src/smpi/colls/allgather-loosely-lr.c
+  src/smpi/colls/allgather-lr.c
+  src/smpi/colls/allgather-NTSLR.c
+  src/smpi/colls/allgather-NTSLR-NB.c
+  src/smpi/colls/allgather-pair.c
+  src/smpi/colls/allgather-rdb.c
+  src/smpi/colls/allgather-rhv.c
+  src/smpi/colls/allgather-ring.c
+  src/smpi/colls/allgather-SMP-NTS.c
+  src/smpi/colls/allgather-smp-simple.c
+  src/smpi/colls/allgather-spreading-simple.c
+  src/smpi/colls/allgatherv-GB.c  
+  src/smpi/colls/allgatherv-pair.c
+  src/smpi/colls/allgatherv-ring.c
+  src/smpi/colls/allreduce-lr.c
+  src/smpi/colls/allreduce-NTS.c
+  src/smpi/colls/allreduce-rab1.c
+  src/smpi/colls/allreduce-rab2.c
+  src/smpi/colls/allreduce-rab-rdb.c
+  #src/smpi/colls/allreduce-rab-reduce-scatter.c
+  src/smpi/colls/allreduce-rab-rsag.c
+  src/smpi/colls/allreduce-rdb.c
+  src/smpi/colls/allreduce-redbcast.c
+  src/smpi/colls/allreduce-smp-binomial.c
+  src/smpi/colls/allreduce-smp-binomial-pipeline.c
+  src/smpi/colls/allreduce-smp-rdb.c
+  src/smpi/colls/allreduce-smp-rsag.c
+  src/smpi/colls/allreduce-smp-rsag-lr.c
+  src/smpi/colls/allreduce-smp-rsag-rab.c
   src/smpi/colls/alltoall-2dmesh.c
   src/smpi/colls/alltoall-3dmesh.c
-  #  src/smpi/colls/alltoall-bruck.c
+  #src/smpi/colls/alltoall-bruck.c
   src/smpi/colls/alltoall-pair.c
   src/smpi/colls/alltoall-pair-light-barrier.c
   src/smpi/colls/alltoall-pair-mpi-barrier.c
@@ -121,6 +157,35 @@ set(SMPI_SRC
   src/smpi/colls/alltoall-ring-mpi-barrier.c
   src/smpi/colls/alltoall-ring-one-barrier.c
   src/smpi/colls/alltoall-simple.c
+  src/smpi/colls/alltoallv-pair.c   
+  src/smpi/colls/alltoallv-pair-light-barrier.c
+  src/smpi/colls/alltoallv-pair-mpi-barrier.c
+  src/smpi/colls/alltoallv-pair-one-barrier.c 
+  src/smpi/colls/alltoallv-ring.c
+  src/smpi/colls/alltoallv-ring-light-barrier.c
+  src/smpi/colls/alltoallv-ring-mpi-barrier.c
+  src/smpi/colls/alltoallv-ring-one-barrier.c
+  src/smpi/colls/alltoallv-bruck.c
+  src/smpi/colls/bcast-arrival-nb.c
+  src/smpi/colls/bcast-arrival-pattern-aware.c
+  src/smpi/colls/bcast-arrival-pattern-aware-wait.c
+  src/smpi/colls/bcast-arrival-scatter.c
+  src/smpi/colls/bcast-binomial-tree.c
+  src/smpi/colls/bcast-flattree.c
+  src/smpi/colls/bcast-flattree-pipeline.c
+  src/smpi/colls/bcast-NTSB.c
+  src/smpi/colls/bcast-NTSL.c
+  src/smpi/colls/bcast-NTSL-Isend.c
+  src/smpi/colls/bcast-scatter-LR-allgather.c
+  src/smpi/colls/bcast-scatter-rdb-allgather.c
+  src/smpi/colls/bcast-SMP-binary.c
+  src/smpi/colls/bcast-SMP-binomial.c
+  src/smpi/colls/bcast-SMP-linear.c
+  src/smpi/colls/reduce-arrival-pattern-aware.c
+  src/smpi/colls/reduce-binomial.c
+  src/smpi/colls/reduce-flat-tree.c
+  src/smpi/colls/reduce-NTSL.c
+  src/smpi/colls/reduce-scatter-gather.c
   )
 
 if(SMPI_F2C)
@@ -553,7 +618,6 @@ set(simgrid_sources
   ${SURF_SRC}
   ${TRACING_SRC}
   ${XBT_SRC}
-  ${SMPI_SRC}
   )
 
 if(${HAVE_JEDULE})
@@ -568,6 +632,13 @@ else()
     )
 endif()
 
+if(enable_smpi)
+  set(simgrid_sources
+    ${simgrid_sources}
+    ${SMPI_SRC}
+    )
+endif()
+
 if(${HAVE_TRACING})
   set(simgrid_sources
     ${simgrid_sources}
@@ -657,6 +728,7 @@ set(DOC_SOURCES
   doc/doxygen/module-sd.doc
   doc/doxygen/module-simix.doc
   doc/doxygen/module-surf.doc
+  doc/doxygen/module-smpi.doc
   doc/doxygen/module-trace.doc
   doc/doxygen/module-xbt.doc
   doc/doxygen/modules.doc
index 4e314ba..6a9c66c 100644 (file)
@@ -61,18 +61,9 @@ add_custom_target(simgrid_update_xml ALL
 install(TARGETS simgrid 
   DESTINATION $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/)
 
-if(enable_smpi)
-  install(TARGETS smpi
-    DESTINATION $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/)
-endif()
-
 if(enable_lib_static AND NOT WIN32)
   install(TARGETS simgrid_static
     DESTINATION $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/)
-  if(enable_smpi)
-    install(TARGETS smpi_static
-      DESTINATION $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/)
-  endif()
 endif()
 
 if(enable_java)
@@ -127,7 +118,6 @@ add_custom_target(uninstall
   COMMAND ${CMAKE_COMMAND} -E  remove_directory ${CMAKE_INSTALL_PREFIX}/doc/simgrid
   COMMAND ${CMAKE_COMMAND} -E  echo "uninstall doc ok"
   COMMAND ${CMAKE_COMMAND} -E  remove -f ${CMAKE_INSTALL_PREFIX}/lib/libsimgrid*
-  COMMAND ${CMAKE_COMMAND} -E  remove -f ${CMAKE_INSTALL_PREFIX}/lib/libsmpi*
   COMMAND ${CMAKE_COMMAND} -E   remove -f ${CMAKE_INSTALL_PREFIX}/lib/lua/5.1/simgrid*
   COMMAND ${CMAKE_COMMAND} -E  echo "uninstall lib ok"
   COMMAND ${CMAKE_COMMAND} -E  remove -f ${CMAKE_INSTALL_PREFIX}/bin/smpicc
index e31007b..0c8e76f 100644 (file)
@@ -15,14 +15,6 @@ if(enable_lib_static)
   add_library(simgrid_static STATIC ${simgrid_sources})
 endif()
 
-if(enable_smpi)
-  add_library(smpi SHARED ${SMPI_SRC})
-  set_target_properties(smpi PROPERTIES VERSION ${libsmpi_version})
-  if(enable_lib_static)
-    add_library(smpi_static STATIC ${SMPI_SRC})
-  endif()
-endif()
-
 if(enable_java)
   include(${CMAKE_HOME_DIRECTORY}/buildtools/Cmake/MakeJava.cmake)
 endif()
@@ -37,9 +29,9 @@ if (enable_supernovae)
   endif()
 
   if(enable_smpi)
-    add_dependencies(smpi ${CMAKE_CURRENT_BINARY_DIR}/src/supernovae_smpi.c)
+    add_dependencies(simgrid ${CMAKE_CURRENT_BINARY_DIR}/src/supernovae_smpi.c)
     if(enable_lib_static)
-      add_dependencies(smpi_static ${CMAKE_CURRENT_BINARY_DIR}/src/supernovae_smpi.c)
+      add_dependencies(simgrid_static ${CMAKE_CURRENT_BINARY_DIR}/src/supernovae_smpi.c)
     endif()
   endif()
 endif()
@@ -126,28 +118,20 @@ if(HAVE_POSIX_GETTIME)
   SET(SIMGRID_DEP "${SIMGRID_DEP} -lrt")
 endif()
 
-target_link_libraries(simgrid  ${SIMGRID_DEP})
-
 # Compute the dependencies of SMPI
 ##################################
-set(SMPI_DEP "")
-if(APPLE)
-  set(SMPI_DEP "-Wl,-U -Wl,_smpi_simulated_main")
-endif()
-if(enable_smpi)
-  target_link_libraries(smpi   simgrid ${SMPI_DEP})
+if(enable_smpi AND APPLE)
+  set(SIMGRID_DEP "${SIMGRID_DEP} -Wl,-U -Wl,_smpi_simulated_main")
 endif()
 
+target_link_libraries(simgrid  ${SIMGRID_DEP})
+
 # Pass dependencies to static libs
 ##################################
 if(enable_lib_static)
   target_link_libraries(simgrid_static         ${SIMGRID_DEP})
   add_dependencies(simgrid_static maintainer_files)
   set_target_properties(simgrid_static PROPERTIES OUTPUT_NAME simgrid)
-  if(enable_smpi)
-    target_link_libraries(smpi_static  simgrid ${SMPI_DEP})
-    set_target_properties(smpi_static PROPERTIES OUTPUT_NAME smpi)
-  endif()
 endif()
 
 # Dependencies from maintainer mode
index 168e85a..081c6e0 100644 (file)
@@ -41,14 +41,3 @@ if(PEXPORTS_PATH)
   add_custom_command(TARGET simgrid POST_BUILD
     COMMAND ${PEXPORTS_PATH}/pexports.exe ${CMAKE_BINARY_DIR}/lib/libsimgrid.dll > ${CMAKE_BINARY_DIR}/lib/libsimgrid.def)
 endif()
-
-if(enable_smpi)
-  set(SMPI_DEP "${LIBRARY_OUTPUT_PATH}/libsimgrid.dll")
-  add_library(smpi SHARED ${SMPI_SRC})
-  set_target_properties(smpi PROPERTIES COMPILE_FLAGS "-D_XBT_DLL_EXPORT -DDLL_EXPORT" LINK_FLAGS "-shared" VERSION ${libsmpi_version} PREFIX "lib" SUFFIX ".dll" IMPORT_PREFIX "lib" IMPORT_SUFFIX ".dll")
-  target_link_libraries(smpi ${SMPI_DEP})
-  if(PEXPORTS_PATH)
-    add_custom_command(TARGET smpi POST_BUILD
-     COMMAND ${PEXPORTS_PATH}/pexports.exe ${CMAKE_BINARY_DIR}/lib/libsmpi.dll > ${CMAKE_BINARY_DIR}/lib/libsmpi.def)
-  endif()
-endif()
index af31674..2df5821 100644 (file)
@@ -41,9 +41,9 @@ option(enable_supernovae "Whether Supernovae mode (helping compiler optimization
 option(enable_msg_deprecated "This option enable the use of msg deprecated functions" off)
 
 if(WIN32)
-  option(enable_smpi "Whether the smpi library is compiled." off)
+  option(enable_smpi "Whether SMPI in included in library." off)
 else()
-  option(enable_smpi "Whether the smpi library is compiled." on)
+  option(enable_smpi "Whether SMPI in included in library." on)
 endif()
 
 mark_as_advanced(HAVE_SSH)
index b399a5c..4b9d212 100644 (file)
@@ -685,6 +685,7 @@ INPUT                  = doxygen/index.doc \
                            doxygen/module-sd.doc \
                            doxygen/module-surf.doc \
                            doxygen/module-simix.doc \
+                           doxygen/module-smpi.doc \
                            doxygen/module-trace.doc \
                            index-API.doc \
                          @top_srcdir@/doc/doxygen/logcategories.doc \
index 0a8cbbd..accc6b9 100644 (file)
@@ -1,9 +1,9 @@
 /*! \page bindings Bindings
 
-\section bindings_binding_Ruby Ruby Binding
+\section MSG_Ruby Ruby Binding
 Check online for our specific [Simgrid-Ruby documentation](http://simgrid.gforge.inria.fr/documentation.html).
 
-\section bindings_binding_Java Java Binding
+\section MSG_Java Java Binding
 Simgrid-java is a java API that let you use [Simgrid](http://simgrid.gforge.inria.fr/)
 MSG API in your favorite language (java). Without it, you would be forced to
 use C or one of the other bindings provided.
index 554ab17..f7c796b 100644 (file)
@@ -2,9 +2,9 @@
 \page inside_extending Extending SimGrid 
 
 We start to put TAGS in simgrid source code for having tutorials to see where is the important parts ans steps to create:
-\li a new MSG functions or a new API.
-\li a new model in surf.
-\li new tags in xml files
+\li \ref simgrid_dev_guide_api
+\li \ref simgrid_dev_guide_model
+\li \ref simgrid_dev_guide_tag
 
 \section simgrid_dev_guide_api How to add a new MSG function?
 Search for expression \"TUTORIAL: New API\".
index a96494e..2241a15 100644 (file)
@@ -1,18 +1,26 @@
 /** \addtogroup MSG_API
 
-      MSG was the first distributed programming environment provided within
-      SimGrid. While almost realistic, it remains quite simple (simplistic?).
-      This describes the native to MSG.
-
-      \section jMSG_who Who should use this (and who shouldn't)
-
-      You should use MSG if you want to study some heuristics for a
-      given problem you don't really want to implement. If you want to
-      use the C programming language, your are in the right
-      section. To use the Java or Ruby programming interfaces, please refer to
-      the documentation provided in the relevant packages.
-
-  \section MSG_funct Offered functionnalities
+MSG was the first distributed programming environment provided within SimGrid,
+and is still the most commonly used nowadays. If you are unsure of the interface
+you should use, they you probably want to use MSG. It constitutes a convenient
+simplification of the reality of distributed systems. It can be used to build
+rather realistic simulations, but remains simple to use: most unpleasant
+technical elements can be abstracted away rather easily.  If you want to use the
+C programming language, your are in the right section. If you prefer not to use
+this venerable but demanding language, please refer to the @ref MSG_Java, the
+@ref MSG_LUA, or the @ref MSG_Ruby (that are distributed separately).
+
+If you think that MSG may not be the interface you need, please consider the
+other user interfaces provided by SimGrid: If you want to use DAGs, have a look
+at the \ref SD_API programming environment. If you want to study an existing MPI
+program, have a look at the \ref SMPI_API one. If none of those programming
+environments fits your needs, you may consider implementing your own directly on
+top of \ref SIMIX_API, or even on top of \ref SURF_API (but you want to contact
+us before digging into these badly documented internal modules).
+
+
+
+\section MSG_funct Offered functionalities
    - \ref msg_simulation
    - \ref m_process_management
    - \ref m_host_management
@@ -86,7 +94,7 @@ details).
 
 /** @defgroup msg_VMs VMs
  *  @ingroup MSG_API
- *  @brief This section describes the interface created to mimick IaaS clouds.
+ *  @brief This section describes the interface created to mimic IaaS clouds.
  *
  *  With it, you can create virtual machines to put your processes
  *  into, and interact directly with the VMs to manage groups of
@@ -146,14 +154,13 @@ This is the lua bindings of the \ref MSG_API interface.
 
 \section lMSG_who Who should use this (and who shouldn't)
 
-If you want to use MSG to study your algorithm, but you don't want to
-use the C language (using \ref MSG_API), then you should use some
-bindings such as this one. The advantage of the lua bindings is that
-they are distributed directly with the main archive (in contrary to
-Java and Ruby bindings, for example, that are distributed separately).
-Another advantage of lua is that there is almost no performance loss
-with regard to the C version (at least there shouln't be any -- it is
-still to be precisely assessed).
+If you want to use MSG to study your algorithm, but you don't want to use the C
+language (using \ref MSG_API), then you should use some bindings such as this
+one. Just like the \ref MSG_Java, the advantage of the lua bindings is that they
+are distributed directly with the main archive (in contrary to Ruby bindings,
+that are distributed separately).  Another advantage of lua is that there is
+almost no performance loss with regard to the C version (at least there
+shouldn't be any -- it is still to be precisely assessed).
 
 \section MSG_Lua_funct  Lua offered functionnalities in MSG
 
diff --git a/doc/doxygen/module-smpi.doc b/doc/doxygen/module-smpi.doc
new file mode 100644 (file)
index 0000000..a5c5099
--- /dev/null
@@ -0,0 +1,161 @@
+/** @addtogroup SMPI_API
+
+This programming environment enables the study of MPI application by
+emulating them on top of the SimGrid simulator. This is particularly
+interesting to study existing MPI applications within the comfort of
+the simulator. The motivation for this work is detailed in the
+reference article (available at http://hal.inria.fr/inria-00527150).
+
+Our goal is to enable the study of *unmodified* MPI applications,
+although we are not quite there yet (see @ref SMPI_what). In
+addition, you can modify your code to speed up your studies or
+otherwise increase their scalability (see @ref SMPI_adapting).
+
+\section SMPI_who Who should use SMPI (and who shouldn't)
+
+SMPI is now considered as stable and you can use it in production. You
+may probably want to read the scientific publications that detail the
+models used and their limits, but this should not be absolutely
+necessary. If you already fluently write and use MPI applications,
+SMPI should sound very familiar to you. Use smpicc instead of mpicc,
+and smpirun instead of mpirun (see below for more details).
+
+Of course, if you don't know what MPI is, the documentation of SMPI
+will seem a bit terse to you. You should pick up a good MPI tutorial
+on the Internet (or a course in your favorite university) and come
+back to SMPI once you know a bit more about MPI. Alternatively, you
+may want to turn to the other SimGrid interfaces such as the 
+\ref MSG_API environment, or the \ref SD_API one.
+
+\section SMPI_what What can run within SMPI?
+
+You can run unmodified MPI applications (both C and Fortran) within
+SMPI, provided that (1) you only use MPI calls that we implemented in
+MPI and (2) you don't use any globals in your application.
+
+\subsection SMPI_what_coverage MPI coverage of SMPI
+
+Our coverage of the interface is very decent, but still incomplete;
+Given the size of the MPI standard, it may well be that we never
+implement absolutely all existing primitives. One sided communications
+and I/O primitives are not targeted for now. Our current state is
+still very decent:¬†we pass most of the MPICH coverage tests.
+
+The full list of not yet implemented functions is documented in the
+file <tt>include/smpi/smpi.h</tt> of the archive, between two lines
+containing the <tt>FIXME</tt> marker. If you really need a missing
+feature, please get in touch with us: we can guide you though the
+SimGrid code to help you implementing it, and we'd glad to integrate
+it in the main project afterward if you contribute them back.
+
+\subsection SMPI_what_globals Issues with the globals
+
+Concerning the globals, the problem comes from the fact that usually,
+MPI processes run as real UNIX processes while they are all folded
+into threads of a unique system process in SMPI. Global variables are
+usually private to each MPI process while they become shared between
+the processes in SMPI. This point is rather problematic, and currently
+forces to modify your application to privatize the global variables.
+
+We tried several techniques to work this around. We used to have a
+script that privatized automatically the globals through static
+analysis of the source code, but it was not robust enough to be used
+in production. This issue, as well as several potential solutions, is
+discussed in this article: "Automatic Handling of Global Variables for
+Multi-threaded MPI Programs",
+available at http://charm.cs.illinois.edu/newPapers/11-23/paper.pdf
+(note that this article does not deal with SMPI but with a concurrent
+solution called AMPI that suffers of the same issue). 
+
+Currently, we have no solution to offer you, because all proposed solutions will
+modify the performance of your application (in the computational
+sections). Sacrificing realism for usability is not very satisfying, so we did
+not implement them yet. You will thus have to modify your application if it uses
+global variables. We are working on another solution, leveraging distributed
+simulation to keep each MPI process within a separate system process, but this
+is far from being ready at the moment.
+
+\section SMPI_compiling Compiling your code
+
+This is very simply done with the <tt>smpicc</tt> script. If you
+already compiled any MPI code before, you already know how to use it.
+If not, you should try to get your MPI code running on top of MPI
+before giving SMPI a spin. Actually, that's very simple even if it's
+the first time you use MPI code: just use smpicc as a compiler (in
+replacement of gcc or your usual compiler), and you're set.
+
+\section SMPI_executing Executing your code on top of the simulator
+
+This is done though the <tt>smpirun</tt> script as follows.
+<tt>my_hostfile.txt</tt> is a classical MPI hostfile (that is, this
+file lists the machines on which the processes must be dispatched, one
+per line)  <tt>my_platform.xml</tt> is a classical SimGrid platform
+file. Of course, the hosts of the hostfile must exist in the provided
+platform. <tt>./program</tt> is the MPI program that you want to
+simulate (must be compiled by <tt>smpicc</tt>) while <tt>-arg</tt> is
+a command-line parameter passed to this program.
+
+\verbatim
+smpirun -hostfile my_hostfile.txt -platform my_platform.xml ./program -arg
+\endverbatim
+
+smpirun accepts other parameters, such as <tt>-np</tt> if you don't
+want to use all the hosts defined in the hostfile, <tt>-map</tt> to
+display on which host each rank gets mapped of <tt>-trace</tt> to
+activate the tracing during the simulation. You can get the full list
+by running
+\verbatim
+smpirun -help
+\endverbatim
+
+\section SMPI_adapting Adapting your MPI code to the use of SMPI
+
+As detailed in the reference article (available at
+http://hal.inria.fr/inria-00527150), you may want to adapt your code
+to improve the simulation performance. But these tricks may seriously
+hinder the result quality (or even prevent the app to run) if used
+wrongly. We assume that if you want to simulate an HPC application,
+you know what you are doing. Don't prove us wrong!
+
+\section SMPI_adapting_size Reducing your memory footprint
+
+If you get short on memory (the whole app is executed on a single node when
+simulated), you should have a look at the SMPI_SHARED_MALLOC and
+SMPI_SHARED_FREE macros. It allows to share memory areas between processes: The
+purpose of these macro is that the same line malloc on each process will point
+to the exact same memory area. So if you have a malloc of 2M and you have 16
+processes, this macro will change your memory consumption from 2M*16 to 2M
+only. Only one block for all processes.
+
+If your program is ok with a block containing garbage value because all
+processes write and read to the same place without any kind of coordination,
+then this macro can dramatically shrink your memory consumption. For example,
+that will be very beneficial to a matrix multiplication code, as all blocks will
+be stored on the same area. Of course, the resulting computations will useless,
+but you can still study the application behavior this way. 
+
+Naturally, this won't work if your code is data-dependent. For example, a Jacobi
+iterative computation depends on the result computed by the code to detect
+convergence conditions, so turning them into garbage by sharing the same memory
+area between processes does not seem very wise. You cannot use the
+SMPI_SHARED_MALLOC macro in this case, sorry.
+
+This feature is demoed by the example file
+<tt>examples/smpi/NAS/DT-folding/dt.c</tt>
+
+\section SMPI_adapting_speed Toward faster simulations
+
+If your application is too slow, try using SMPI_SAMPLE_LOCAL,
+SMPI_SAMPLE_GLOBAL and friends to indicate which computation loops can
+be sampled. Some of the loop iterations will be executed to measure
+their duration, and this duration will be used for the subsequent
+iterations. These samples are done per processor with
+SMPI_SAMPLE_LOCAL, and shared between all processors with
+SMPI_SAMPLE_GLOBAL. Of course, none of this will work if the execution
+time of your loop iteration are not stable.
+
+This feature is demoed by the example file 
+<tt>examples/smpi/NAS/EP-sampling/ep.c</tt>
+
+
+*/
\ No newline at end of file
index d21c24c..7b5f076 100644 (file)
@@ -2,19 +2,6 @@
 @defgroup MSG_API      MSG
 @brief Simple programming environment
 
-MSG was the first distributed programming environment provided within
-SimGrid. While almost realistic, it remains quite simple
-(simplistic?).
-
-@section MSG_who Who should use this (and who shouldn't)
-
-You should use this module if you want to study some heuristics for a
-given problem you don't really want to implement. If you want to use
-DAGs, have a look at the \ref SD_API programming environment. If you
-want to study an existing MPI program, have a look at the \ref
-SMPI_API one. If none of those programming environments fits your
-needs, you may consider implementing your own directly on top of 
-\ref SURF_API (but you probably want to contact us before). 
 */
 
 /** 
@@ -52,101 +39,6 @@ parameter in the command line (see \ref tracing for details).
 
 /** \defgroup SMPI_API      SMPI
     \brief Programming environment for the simulation of MPI applications
-
-This programming environment permits to study existing MPI application
-by emulating them on top of the SimGrid simulator. In other words, it
-will constitute an emulation solution for parallel codes. You don't
-even have to modify your code for that, although that may help, as
-detailed below.
-
-\section SMPI_who Who should use SMPI (and who shouldn't)
-
-You should use this programming environment of the SimGrid suite if
-you want to study existing MPI applications.  If you want to study
-some heuristics for a given problem (and if your goal is to produce
-theorems and publications, not code), have a look at the \ref MSG_API
-environment, or the \ref SD_API one if you need to use DAGs. If none
-of those programming environments fits your needs, you may consider
-implementing your own directly on top of \ref SURF_API (but you
-probably want to contact us before).
-
-\section SMPI_what What can run within SMPI?
-
-You can run unmodified MPI applications (both C and Fortran) within
-SMPI, provided you only use MPI calls that we implemented in MPI. Our
-coverage of the interface is not bad, but will probably never be
-complete. One sided communications and I/O primitives are not targeted
-for now. The full list of not yet implemented functions is available
-in file <tt>include/smpi/smpi.h</tt> of the archive, between two lines
-containing the <tt>FIXME</tt> marker. If you really need a missing
-feature, please get in touch with us: we can guide you though the
-SimGrid code to help you implementing it, and we'd glad to integrate
-it in the main project afterward if you contribute them back.
-
-\section SMPI_adapting Adapting your MPI code to the use of SMPI
-
-As detailed in the reference article (available at
-http://hal.inria.fr/inria-00527150), you may want to adapt your code
-to improve the simulation performance. But these tricks may seriously
-hinder the result qualtity (or even prevent the app to run) if used
-wrongly. We assume that if you want to simulate an HPC application,
-you know what you are doing. Don't prove us wrong!
-
-If you get short on memory (the whole app is executed on a single node
-when simulated), you should have a look at the SMPI_SHARED_MALLOC and
-SMPI_SHARED_FREE macros. It allows to share memory areas between
-processes. For example, matrix multiplication code may want to store
-the blocks on the same area. Of course, the resulting computations
-will useless, but you can still study the application behavior this
-way. Of course, if your code is data-dependent, this won't work.
-
-If your application is too slow, try using SMPI_SAMPLE_LOCAL,
-SMPI_SAMPLE_GLOBAL and friends to indicate which computation loops can
-be sampled. Some of the loop iterations will be executed to measure
-their duration, and this duration will be used for the subsequent
-iterations. These samples are done per processor with
-SMPI_SAMPLE_LOCAL, and shared between all processors with
-SMPI_SAMPLE_GLOBAL. Of course, none of this will work if the execution
-time of your loop iteration are not stable.
-
-Yes, that's right, these macros are not documented yet, but we'll fix
-it as soon as time permits. Sorry about that -- patch welcomed!
-Meanwhile, grep for them on the examples for more information.
-
-\section SMPI_compiling Compiling your code
-
-This is very simply done with the <tt>smpicc</tt> script. If you
-already compiled any MPI code before, you already know how to use it.
-If not, you should try to get your MPI code running on top of MPI
-before giving SMPI a spin. Actually, that's very simple even if it's
-the first time you use MPI code: just use smpicc as a compiler (in
-replacement of gcc or your usual compiler), and you're set.
-
-\section SMPI_executing Executing your code on top of the simulator
-
-This is done though the <tt>smpirun</tt> script as follows.
-<tt>my_hostfile.txt</tt> is a classical MPI hostfile (that is, this
-file lists the machines on which the processes must be dispatched, one
-per line)  <tt>my_platform.xml</tt> is a classical SimGrid platform
-file. Of course, the hosts of the hostfile must exist in the provided
-platform. <tt>./program</tt> is the MPI program that you want to
-simulate (must be compiled by <tt>smpicc</tt>) while <tt>-arg</tt> is
-a command-line parameter passed to this program.
-
-\verbatim
-smpirun -hostfile my_hostfile.txt -platform my_platform.xml ./program -arg
-\endverbatim
-
-smpirun accepts other parameters, such as <tt>-np</tt> if you don't
-want to use all the hosts defined in the hostfile, <tt>-map</tt> to
-display on which host each rank gets mapped of <tt>-trace</tt> to
-activate the tracing during the simulation. You can get the full list
-by running
-\verbatim
-smpirun -help
-\endverbatim
-
-
 */
 
 
index d9765bc..d556a5e 100644 (file)
@@ -4,15 +4,16 @@ if(HAVE_MC)
   set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
 
   file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/")
-  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/chord/")
+  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/chord_liveness/")
 
   add_executable(centralized centralized_mutex.c)
   add_executable(bugged1     bugged1.c)
   add_executable(bugged2      bugged2.c)
   add_executable(bugged3          bugged3.c)
+  add_executable(electric_fence           electric_fence.c)
   add_executable(bugged1_liveness bugged1_liveness.c)
   add_executable(bugged2_liveness bugged2_liveness.c)
-  add_executable(chord/chord_liveness chord/chord_liveness.c)
+  add_executable(chord_liveness/chord_liveness chord_liveness/chord_liveness.c)
   add_executable(test/snapshot_comparison1 test/snapshot_comparison1.c)
   add_executable(test/snapshot_comparison2 test/snapshot_comparison2.c)
   add_executable(test/snapshot_comparison3 test/snapshot_comparison3.c)
@@ -23,9 +24,10 @@ if(HAVE_MC)
   target_link_libraries(bugged1     simgrid )
   target_link_libraries(bugged2     simgrid )
   target_link_libraries(bugged3     simgrid )
+  target_link_libraries(electric_fence     simgrid )
   target_link_libraries(bugged1_liveness     simgrid )
   target_link_libraries(bugged2_liveness     simgrid )
-  target_link_libraries(chord/chord_liveness     simgrid )
+  target_link_libraries(chord_liveness/chord_liveness     simgrid )
   target_link_libraries(test/snapshot_comparison1     simgrid )
   target_link_libraries(test/snapshot_comparison2     simgrid )
   target_link_libraries(test/snapshot_comparison3     simgrid )
@@ -39,7 +41,9 @@ set(tesh_files
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged1.tesh
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged1_liveness.tesh
   ${CMAKE_CURRENT_SOURCE_DIR}/centralized.tesh
-  ${CMAKE_CURRENT_SOURCE_DIR}/chord/chord_neverjoin.tesh
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/chord_neverjoin.tesh
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/chord_neverdeliver.tesh 
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/chord_neverjoin_timeout_visited.tesh 
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison1.tesh
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison2.tesh
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison3.tesh
@@ -54,10 +58,10 @@ set(xml_files
   ${CMAKE_CURRENT_SOURCE_DIR}/deploy_bugged2_liveness.xml
   ${CMAKE_CURRENT_SOURCE_DIR}/deploy_bugged2.xml
   ${CMAKE_CURRENT_SOURCE_DIR}/deploy_bugged3.xml
+  ${CMAKE_CURRENT_SOURCE_DIR}/deploy_electric_fence.xml
   ${CMAKE_CURRENT_SOURCE_DIR}/deploy_mutex.xml
-  ${CMAKE_CURRENT_SOURCE_DIR}/deploy_random_test.xml
   ${CMAKE_CURRENT_SOURCE_DIR}/platform.xml
-  ${CMAKE_CURRENT_SOURCE_DIR}/chord/deploy_chord_liveness.xml
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/deploy_chord_liveness.xml
   ${CMAKE_CURRENT_SOURCE_DIR}/test/deploy_snapshot_comparison.xml
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison_platform.xml
   PARENT_SCOPE
@@ -69,11 +73,11 @@ set(examples_src
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged2.c
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged2_liveness.c
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged3.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/electric_fence.c
   ${CMAKE_CURRENT_SOURCE_DIR}/centralized_mutex.c
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged1_liveness.h
   ${CMAKE_CURRENT_SOURCE_DIR}/bugged2_liveness.h
-  ${CMAKE_CURRENT_SOURCE_DIR}/chord/chord_liveness.c
-  ${CMAKE_CURRENT_SOURCE_DIR}/chord/chord_liveness.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/chord_liveness.c
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison1.c
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison2.c
   ${CMAKE_CURRENT_SOURCE_DIR}/test/snapshot_comparison3.c
@@ -86,7 +90,8 @@ set(bin_files
   ${CMAKE_CURRENT_SOURCE_DIR}/parse_dwarf
   ${CMAKE_CURRENT_SOURCE_DIR}/promela_bugged1_liveness
   ${CMAKE_CURRENT_SOURCE_DIR}/promela_bugged2_liveness
-  ${CMAKE_CURRENT_SOURCE_DIR}/chord/promela_chord_liveness
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/promela_chord_neverjoin
+  ${CMAKE_CURRENT_SOURCE_DIR}/chord_liveness/promela_chord_neverdeliver
   ${CMAKE_CURRENT_SOURCE_DIR}/test/promela
   PARENT_SCOPE
   )
index 6a11193..dbdc4eb 100644 (file)
@@ -9,21 +9,6 @@ $ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%
 > [  0.000000] (1:server@HostA) OK
 > [  0.000000] (4:client@HostD) Sent!
 > [  0.000000] (2:client@HostB) Sent!
-> [  0.000000] (1:server@HostA) OK
-> [  0.000000] (3:client@HostC) Sent!
-> [  0.000000] (4:client@HostD) Sent!
-> [  0.000000] (2:client@HostB) Sent!
-> [  0.000000] (3:client@HostC) Sent!
-> [  0.000000] (1:server@HostA) OK
-> [  0.000000] (4:client@HostD) Sent!
-> [  0.000000] (2:client@HostB) Sent!
-> [  0.000000] (1:server@HostA) OK
-> [  0.000000] (3:client@HostC) Sent!
-> [  0.000000] (4:client@HostD) Sent!
-> [  0.000000] (2:client@HostB) Sent!
-> [  0.000000] (3:client@HostC) Sent!
-> [  0.000000] (1:server@HostA) OK
-> [  0.000000] (4:client@HostD) Sent!
 > [  0.000000] (2:client@HostB) Sent!
 > [  0.000000] (1:server@HostA) **************************
 > [  0.000000] (1:server@HostA) *** PROPERTY NOT VALID ***
@@ -39,6 +24,6 @@ $ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%
 > [  0.000000] (1:server@HostA) [(1)server] iRecv (dst=server, buff=(verbose only), size=(verbose only))
 > [  0.000000] (1:server@HostA) [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
 > [  0.000000] (1:server@HostA) [(1)server] Wait (comm=(verbose only) [(3)client -> (1)server])
-> [  0.000000] (1:server@HostA) Expanded states = 36
-> [  0.000000] (1:server@HostA) Visited states = 75
-> [  0.000000] (1:server@HostA) Executed transitions = 70
+> [  0.000000] (1:server@HostA) Expanded states = 17
+> [  0.000000] (1:server@HostA) Visited states = 32
+> [  0.000000] (1:server@HostA) Executed transitions = 30
index b0f05b3..6954ef6 100644 (file)
@@ -2,43 +2,44 @@
 
 ! expect signal SIGABRT
 ! timeout 200
-$ ${bindir:=.}/bugged1_liveness --cfg=model-check:1 --cfg=contexts/factory:ucontext
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [mc_global/INFO] Check the liveness property promela_bugged1_liveness
-> [Fafard:client:(2) 0.000000] [bugged1_liveness/INFO] Ask the request
-> [Boivin:client:(3) 0.000000] [bugged1_liveness/INFO] Ask the request
-> [Fafard:client:(2) 0.000000] [bugged1_liveness/INFO] Propositions changed : r=1, cs=0
-> [Tremblay:coordinator:(1) 0.000000] [bugged1_liveness/INFO] CS idle. Grant immediatly
-> [Boivin:client:(3) 0.000000] [bugged1_liveness/INFO] 2 got the answer. Sleep a bit and release it
-> [Tremblay:coordinator:(1) 0.000000] [bugged1_liveness/INFO] CS release. resource now idle
-> [Boivin:client:(3) 0.000000] [bugged1_liveness/INFO] Ask the request
-> [Tremblay:coordinator:(1) 0.000000] [bugged1_liveness/INFO] CS idle. Grant immediatly
-> [0.000000] [mc_liveness/INFO] Next pair (depth = 22, 1 interleave) already reached !
-> [0.000000] [mc_liveness/INFO] *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-> [0.000000] [mc_liveness/INFO] |             ACCEPTANCE CYCLE            |
-> [0.000000] [mc_liveness/INFO] *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-> [0.000000] [mc_liveness/INFO] Counter-example that violates formula :
-> [0.000000] [mc_global/INFO] [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(2)client] iSend (src=client, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)coordinator] Wait (comm=(verbose only) [(2)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(2)client] Wait (comm=(verbose only) [(2)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(2)client] iRecv (dst=client, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)coordinator] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(1)coordinator] iSend (src=coordinator, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(3)client] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(3)client] iRecv (dst=client, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)coordinator] Wait (comm=(verbose only) [(1)coordinator -> (3)client])
-> [0.000000] [mc_global/INFO] [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(3)client] Wait (comm=(verbose only) [(1)coordinator -> (3)client])
-> [0.000000] [mc_global/INFO] [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)coordinator] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(3)client] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)coordinator] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
-> [0.000000] [mc_global/INFO] [(1)coordinator] iSend (src=coordinator, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] Expanded pairs = 23
-> [0.000000] [mc_global/INFO] Visited pairs = 21
-> [0.000000] [mc_global/INFO] Executed transitions = 21
+$ ${bindir:=.}/bugged1_liveness --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext
+> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+> [  0.000000] (0:@) Check the liveness property promela_bugged1_liveness
+> [  0.000000] (2:client@Fafard) Ask the request
+> [  0.000000] (3:client@Boivin) Ask the request
+> [  0.000000] (2:client@Fafard) Propositions changed : r=1, cs=0
+> [  0.000000] (1:coordinator@Tremblay) CS idle. Grant immediatly
+> [  0.000000] (3:client@Boivin) 2 got the answer. Sleep a bit and release it
+> [  0.000000] (1:coordinator@Tremblay) CS release. resource now idle
+> [  0.000000] (3:client@Boivin) Ask the request
+> [  0.000000] (1:coordinator@Tremblay) CS idle. Grant immediatly
+> [  0.000000] (0:@) Next pair (depth = 22, 1 interleave) already reached (equal to state 11) !
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) |             ACCEPTANCE CYCLE            |
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) Counter-example that violates formula :
+> [  0.000000] (0:@) [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)client] iSend (src=client, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)coordinator] Wait (comm=(verbose only) [(2)client -> (1)coordinator])
+> [  0.000000] (0:@) [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)client] Wait (comm=(verbose only) [(2)client -> (1)coordinator])
+> [  0.000000] (0:@) [(2)client] iRecv (dst=client, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)coordinator] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
+> [  0.000000] (0:@) [(1)coordinator] iSend (src=coordinator, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)client] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
+> [  0.000000] (0:@) [(3)client] iRecv (dst=client, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)coordinator] Wait (comm=(verbose only) [(1)coordinator -> (3)client])
+> [  0.000000] (0:@) [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)client] Wait (comm=(verbose only) [(1)coordinator -> (3)client])
+> [  0.000000] (0:@) [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)coordinator] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
+> [  0.000000] (0:@) [(1)coordinator] iRecv (dst=coordinator, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)client] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
+> [  0.000000] (0:@) [(3)client] iSend (src=client, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)coordinator] Wait (comm=(verbose only) [(3)client -> (1)coordinator])
+> [  0.000000] (0:@) [(1)coordinator] iSend (src=coordinator, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) Expanded pairs = 23
+> [  0.000000] (0:@) Visited pairs = 21
+> [  0.000000] (0:@) Executed transitions = 21
+
diff --git a/examples/msg/mc/chord/chord_liveness.h b/examples/msg/mc/chord/chord_liveness.h
deleted file mode 100644 (file)
index e522b77..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CHORD_LIVENESS_H
-#define _CHORD_LIVENESS_H
-
-int predJoin(void);
-
-#endif
diff --git a/examples/msg/mc/chord/chord_neverjoin.tesh b/examples/msg/mc/chord/chord_neverjoin.tesh
deleted file mode 100644 (file)
index b458c9c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#! ./tesh
-
-! expect signal SIGABRT
-! timeout 200
-$ ${bindir:=.}/chord_liveness --cfg=model-check:1 --cfg=contexts/factory:ucontext
-> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'model-check' to '1'
-> [0.000000] [mc_global/INFO] Check the liveness property promela_chord_liveness
-> [Jean_Yves:node:(1) 0.000000] [chord_liveness/INFO] Joining the ring with id 14, knowing node 1
-> [Boivin:node:(2) 0.000000] [chord_liveness/INFO] Joining the ring with id 8, knowing node 1
-> [Jacquelin:node:(3) 0.000000] [chord_liveness/INFO] A transfer has occured
-> [Jacquelin:node:(3) 0.000000] [chord_liveness/INFO] The task was successfully received by node 1
-> [Jean_Yves:node:(1) 0.000000] [chord_liveness/INFO] Node 14 joined the ring
-> [0.000000] [mc_liveness/INFO] Next pair (depth = 11, 2 interleave) already reached !
-> [0.000000] [mc_liveness/INFO] *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-> [0.000000] [mc_liveness/INFO] |             ACCEPTANCE CYCLE            |
-> [0.000000] [mc_liveness/INFO] *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-> [0.000000] [mc_liveness/INFO] Counter-example that violates formula :
-> [0.000000] [mc_global/INFO] [(1)node] iSend (src=node, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(2)node] iSend (src=node, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(3)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)node] Wait (comm=(verbose only) [(1)node -> (3)node])
-> [0.000000] [mc_global/INFO] [(1)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(3)node] Test TRUE (comm=(verbose only) [(1)node -> (3)node])
-> [0.000000] [mc_global/INFO] [(3)node] iSend (src=node, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)node] Wait (comm=(verbose only) [(3)node -> (1)node])
-> [0.000000] [mc_global/INFO] [(1)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
-> [0.000000] [mc_global/INFO] [(1)node] Test FALSE (comm=(verbose only))
-> [0.000000] [mc_global/INFO] Expanded pairs = 14
-> [0.000000] [mc_global/INFO] Visited pairs = 10
-> [0.000000] [mc_global/INFO] Executed transitions = 10
similarity index 90%
rename from examples/msg/mc/chord/chord_liveness.c
rename to examples/msg/mc/chord_liveness/chord_liveness.c
index 4856395..f7d1a0d 100644 (file)
@@ -10,7 +10,6 @@
 #include "xbt/log.h"
 #include "xbt/asserts.h"
 #include "simgrid/modelchecker.h"
-#include "chord_liveness.h"
 #include "mc/mc.h"
 
 /** @addtogroup MSG_examples
@@ -121,8 +120,9 @@ static void check_predecessor(node_t node);
 static void random_lookup(node_t);
 static void quit_notify(node_t node);
 
-/* Global variable corresponding to atomic proposition */
+/* Global variables corresponding to atomic propositions */
 int node_join = 0;
+int node_deliver = 0;
 
 /**
  * \brief Global initialization of the Chord simulation.
@@ -209,9 +209,11 @@ static void get_mailbox(int node_id, char* mailbox)
 static void task_free(void* task)
 {
   // TODO add a parameter data_free_function to MSG_task_create?
-  xbt_free(MSG_task_get_data(task));
-  MSG_task_destroy(task);
-  task = NULL;
+  if(task != NULL){
+    xbt_free(MSG_task_get_data(task));
+    MSG_task_destroy(task);
+    task = NULL;
+  }
 }
 
 /**
@@ -329,7 +331,6 @@ int node(int argc, char *argv[])
     if(join_success){
       XBT_INFO("Node %d joined the ring", node.id);
       node_join = 1; 
-      //MC_compare();
     }
   }
 
@@ -347,34 +348,71 @@ int node(int argc, char *argv[])
 
       if (!MSG_comm_test(node.comm_receive)) {
 
-        // no task was received: make some periodic calls
-        if (MSG_get_clock() >= next_stabilize_date) {
-          stabilize(&node);
-          next_stabilize_date = MSG_get_clock() + periodic_stabilize_delay;
-        }
-        else if (MSG_get_clock() >= next_fix_fingers_date) {
-          fix_fingers(&node);
-          next_fix_fingers_date = MSG_get_clock() + periodic_fix_fingers_delay;
-        }
-        else if (MSG_get_clock() >= next_check_predecessor_date) {
-          check_predecessor(&node);
-          next_check_predecessor_date = MSG_get_clock() + periodic_check_predecessor_delay;
-        }
-        else if (MSG_get_clock() >= next_lookup_date) {
-          random_lookup(&node);
-          next_lookup_date = MSG_get_clock() + periodic_lookup_delay;
-        }
-        else {
-          // nothing to do: sleep for a while
-          MSG_process_sleep(5);
-        }
+        #ifdef HAVE_MC
+          if(MC_is_active()){
+            if(MC_random()){
+              stabilize(&node);
+            }else if(MC_random()){
+              fix_fingers(&node);
+            }else if(MC_random()){
+              check_predecessor(&node);
+            }else if(MC_random()){
+              random_lookup(&node);
+            }else{
+              MSG_process_sleep(5);
+            }
+          }else{
+            if (MSG_get_clock() >= next_stabilize_date) {
+              stabilize(&node);
+              next_stabilize_date = MSG_get_clock() + periodic_stabilize_delay;
+            }
+            else if (MSG_get_clock() >= next_fix_fingers_date) {
+              fix_fingers(&node);
+              next_fix_fingers_date = MSG_get_clock() + periodic_fix_fingers_delay;
+            }
+            else if (MSG_get_clock() >= next_check_predecessor_date) {
+              check_predecessor(&node);
+              next_check_predecessor_date = MSG_get_clock() + periodic_check_predecessor_delay;
+            }
+            else if (MSG_get_clock() >= next_lookup_date) {
+              random_lookup(&node);
+              next_lookup_date = MSG_get_clock() + periodic_lookup_delay;
+            }
+            else {
+              // nothing to do: sleep for a while
+              MSG_process_sleep(5);
+            }
+          }
+        #else
+          if (MSG_get_clock() >= next_stabilize_date) {
+            stabilize(&node);
+            next_stabilize_date = MSG_get_clock() + periodic_stabilize_delay;
+          }
+          else if (MSG_get_clock() >= next_fix_fingers_date) {
+            fix_fingers(&node);
+            next_fix_fingers_date = MSG_get_clock() + periodic_fix_fingers_delay;
+          }
+          else if (MSG_get_clock() >= next_check_predecessor_date) {
+            check_predecessor(&node);
+            next_check_predecessor_date = MSG_get_clock() + periodic_check_predecessor_delay;
+          }
+          else if (MSG_get_clock() >= next_lookup_date) {
+            random_lookup(&node);
+            next_lookup_date = MSG_get_clock() + periodic_lookup_delay;
+          }
+          else {
+            // nothing to do: sleep for a while
+            MSG_process_sleep(5);
+          }
+        #endif
+
       }else{
 
         if (node.comm_receive) {
 
-          XBT_INFO("A transfer has occured");
+          node_deliver = 0;
 
-          //MC_compare();
+          XBT_INFO("A transfer has occured");
 
           // a transfer has occured
 
@@ -426,6 +464,7 @@ static void handle_task(node_t node, msg_task_t task) {
   switch (type) {
 
     case TASK_FIND_SUCCESSOR:
+      node_deliver = 1;
       XBT_DEBUG("Receiving a 'Find Successor' request from %s for id %d",
           task_data->issuer_host_name, task_data->request_id);
       // is my successor the successor?
@@ -895,10 +934,14 @@ static void random_lookup(node_t node)
   find_successor(node, id);
 }
 
-int predJoin(void){
+static int predJoin(void){
   return node_join;
 }
 
+static int predDeliver(void){
+  return node_deliver;
+}
+
 
 /**
  * \brief Main function.
@@ -906,13 +949,13 @@ int predJoin(void){
 int main(int argc, char *argv[])
 {
   MSG_init(&argc, argv);
-  /*if (argc < 3) {
+  if (argc < 3) {
     printf("Usage: %s [-nb_bits=n] [-timeout=t] platform_file deployment_file\n", argv[0]);
-    printf("example: %s ../msg_platform.xml chord.xml\n", argv[0]);
+    printf("example: %s ../../msg_platform.xml deploy_chord_liveness.xml\n", argv[0]);
     exit(1);
-    }*/
+  }
 
-  char **options = &argv[0];
+  char **options = &argv[1];
   while (!strncmp(options[0], "-", 1)) {
 
     int length = strlen("-nb_bits=");
@@ -934,21 +977,20 @@ int main(int argc, char *argv[])
     options++;
   }
 
-  //const char* platform_file = options[0];
-  //const char* application_file = options[1];
+  const char* platform_file = options[0];
+  const char* application_file = options[1];
 
   chord_initialize();
 
-  MSG_config("model-check/property","promela_chord_liveness");
   MC_automaton_new_propositional_symbol("join", &predJoin);
+  MC_automaton_new_propositional_symbol("deliver", &predDeliver);
 
-  MSG_create_environment("../../msg_platform.xml");
-
+  MSG_create_environment(platform_file);
+  
   MSG_function_register("node", node);
-  MSG_launch_application("deploy_chord_liveness.xml");
+  MSG_launch_application(application_file);
 
   msg_error_t res = MSG_main();
-  //XBT_CRITICAL("Messages created: %ld", smx_total_comms);
   XBT_INFO("Simulated time: %g", MSG_get_clock());
 
   chord_exit();
diff --git a/examples/msg/mc/chord_liveness/chord_neverdeliver.tesh b/examples/msg/mc/chord_liveness/chord_neverdeliver.tesh
new file mode 100644 (file)
index 0000000..fed20cb
--- /dev/null
@@ -0,0 +1,35 @@
+#! ./tesh
+
+! expect signal SIGABRT
+! timeout 200
+$ ${bindir:=.}/chord_liveness ../../msg_platform.xml deploy_chord_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/property:promela_chord_neverdeliver
+> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+> [  0.000000] (0:@) Configuration change: Set 'model-check/property' to 'promela_chord_neverdeliver'
+> [  0.000000] (0:@) Check the liveness property promela_chord_neverdeliver
+> [  0.000000] (1:node@Jean_Yves) Joining the ring with id 14, knowing node 1
+> [  0.000000] (2:node@Boivin) Joining the ring with id 8, knowing node 1
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Node 14 joined the ring
+> [  0.000000] (0:@) Next pair (depth = 15, 2 interleave) already reached (equal to state 13) !
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) |             ACCEPTANCE CYCLE            |
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) Counter-example that violates formula :
+> [  0.000000] (0:@) [(1)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] Wait (comm=(verbose only) [(1)node -> (3)node])
+> [  0.000000] (0:@) [(1)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)node] Test TRUE (comm=(verbose only) [(1)node -> (3)node])
+> [  0.000000] (0:@) [(3)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] Wait (comm=(verbose only) [(3)node -> (1)node])
+> [  0.000000] (0:@) [(1)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] Test FALSE (comm=(verbose only))
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) Expanded pairs = 24
+> [  0.000000] (0:@) Visited pairs = 14
+> [  0.000000] (0:@) Executed transitions = 14
diff --git a/examples/msg/mc/chord_liveness/chord_neverjoin.tesh b/examples/msg/mc/chord_liveness/chord_neverjoin.tesh
new file mode 100644 (file)
index 0000000..56d3a28
--- /dev/null
@@ -0,0 +1,37 @@
+#! ./tesh
+
+! expect signal SIGABRT
+! timeout 200
+$ ${bindir:=.}/chord_liveness ../../msg_platform.xml deploy_chord_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/property:promela_chord_neverjoin
+> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+> [  0.000000] (0:@) Configuration change: Set 'model-check/property' to 'promela_chord_neverjoin'
+> [  0.000000] (0:@) Check the liveness property promela_chord_neverjoin
+> [  0.000000] (1:node@Jean_Yves) Joining the ring with id 14, knowing node 1
+> [  0.000000] (2:node@Boivin) Joining the ring with id 8, knowing node 1
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Node 14 joined the ring
+> [  0.000000] (0:@) Next pair (depth = 15, 2 interleave) already reached (equal to state 11) !
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) |             ACCEPTANCE CYCLE            |
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) Counter-example that violates formula :
+> [  0.000000] (0:@) [(1)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] Wait (comm=(verbose only) [(1)node -> (3)node])
+> [  0.000000] (0:@) [(1)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)node] Test TRUE (comm=(verbose only) [(1)node -> (3)node])
+> [  0.000000] (0:@) [(3)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] Wait (comm=(verbose only) [(3)node -> (1)node])
+> [  0.000000] (0:@) [(1)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] Test FALSE (comm=(verbose only))
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(1)node] MC_RANDOM (0)
+> [  0.000000] (0:@) Expanded pairs = 22
+> [  0.000000] (0:@) Visited pairs = 14
+> [  0.000000] (0:@) Executed transitions = 14
+
+
diff --git a/examples/msg/mc/chord_liveness/chord_neverjoin_timeout_visited.tesh b/examples/msg/mc/chord_liveness/chord_neverjoin_timeout_visited.tesh
new file mode 100644 (file)
index 0000000..ed80aeb
--- /dev/null
@@ -0,0 +1,105 @@
+#! ./tesh
+
+! expect signal SIGABRT
+! timeout 200
+$ ${bindir:=.}/chord_liveness ../../msg_platform.xml deploy_chord_liveness.xml --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" --cfg=contexts/factory:ucontext --cfg=model-check/property:promela_chord_neverjoin --cfg=model-check/timeout:1 --cfg=model-check/visited:100
+> [  0.000000] (0:@) Configuration change: Set 'model-check' to '1'
+> [  0.000000] (0:@) Configuration change: Set 'model-check/property' to 'promela_chord_neverjoin'
+> [  0.000000] (0:@) Configuration change: Set 'model-check/timeout' to '1'
+> [  0.000000] (0:@) Configuration change: Set 'model-check/visited' to '100'
+> [  0.000000] (0:@) Check the liveness property promela_chord_neverjoin
+> [  0.000000] (1:node@Jean_Yves) Joining the ring with id 14, knowing node 1
+> [  0.000000] (2:node@Boivin) Joining the ring with id 8, knowing node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (2:node@Boivin) Cannot join the ring.
+> [  0.000000] (1:node@Jean_Yves) Cannot join the ring.
+> [  0.000000] (3:node@Jacquelin) A transfer has occured
+> [  0.000000] (3:node@Jacquelin) The task was successfully received by node 1
+> [  0.000000] (2:node@Boivin) Node 8 joined the ring
+> [  0.000000] (0:@) Next pair (depth = 16, 2 interleave) already reached (equal to state 71) !
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) |             ACCEPTANCE CYCLE            |
+> [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+> [  0.000000] (0:@) Counter-example that violates formula :
+> [  0.000000] (0:@) [(1)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)node] WaitTimeout (comm=(verbose only))
+> [  0.000000] (0:@) [(2)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)node] Wait (comm=(verbose only) [(2)node -> (3)node])
+> [  0.000000] (0:@) [(2)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)node] Test TRUE (comm=(verbose only) [(2)node -> (3)node])
+> [  0.000000] (0:@) [(3)node] iSend (src=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)node] Wait (comm=(verbose only) [(3)node -> (2)node])
+> [  0.000000] (0:@) [(2)node] iRecv (dst=node, buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)node] Test FALSE (comm=(verbose only))
+> [  0.000000] (0:@) [(2)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(2)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(2)node] MC_RANDOM (0)
+> [  0.000000] (0:@) [(2)node] MC_RANDOM (0)
+> [  0.000000] (0:@) Expanded pairs = 82
+> [  0.000000] (0:@) Visited pairs = 337
+> [  0.000000] (0:@) Executed transitions = 360
\ No newline at end of file
diff --git a/examples/msg/mc/chord_liveness/promela_chord_neverdeliver b/examples/msg/mc/chord_liveness/promela_chord_neverdeliver
new file mode 100644 (file)
index 0000000..d102137
--- /dev/null
@@ -0,0 +1,12 @@
+never { /* !(!(GFdeliver)) */
+T0_init :    /* init */
+       if
+       :: (deliver) -> goto accept_S1
+       :: (1) -> goto T0_init
+       fi;
+accept_S1 :    /* 1 */
+       if
+       :: (deliver) -> goto accept_S1
+       :: (1) -> goto T0_init
+       fi;
+}
\ No newline at end of file
similarity index 71%
rename from examples/msg/mc/deploy_random_test.xml
rename to examples/msg/mc/deploy_electric_fence.xml
index 31415a5..3fd4d5a 100644 (file)
@@ -4,14 +4,10 @@
   <process host="HostA" function="server">
     <argument value="0"/>
   </process>
-  <process host="HostB" function="server">
-    <argument value="0"/>
-  </process>
-
-<!--  <process host="HostB" function="client">
+  <process host="HostB" function="client">
     <argument value="1"/>
   </process>  
   <process host="HostC" function="client">
     <argument value="2"/>
-  </process> -->
+  </process>
 </platform>
diff --git a/examples/msg/mc/electric_fence.c b/examples/msg/mc/electric_fence.c
new file mode 100644 (file)
index 0000000..cfe23b7
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+
+/******************** Non-deterministic message ordering  *********************/
+/* This example implements one process which receives messages from two other */
+/* processes. There is no bug on it, it is just provided to test the soundness*/ 
+/* of the state space reduction with DPOR, if the maximum depth (defined with */
+/* --cfg=model-check/max_depth:) is reached.                                  */
+/******************************************************************************/
+
+#include <msg/msg.h>
+#include <simgrid/modelchecker.h>
+
+#define N 2
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(electric_fence, "Example to check the soundness of DPOR");
+
+int server(int argc, char *argv[]);
+int client(int argc, char *argv[]);
+
+int server(int argc, char *argv[])
+{
+  msg_task_t task1 = NULL, task2 = NULL;
+  msg_comm_t comm_received1 = NULL, comm_received2 = NULL;
+
+  comm_received1 = MSG_task_irecv(&task1, "mymailbox");
+  comm_received2 = MSG_task_irecv(&task2, "mymailbox");
+
+  MSG_comm_wait(comm_received1, -1);
+  MSG_comm_wait(comm_received2, -1);
+
+  XBT_INFO("OK");
+  return 0;
+}
+
+int client(int argc, char *argv[])
+{
+
+  msg_task_t task = MSG_task_create(argv[1], 0, 10000, NULL);
+
+  MSG_task_send(task, "mymailbox");
+  
+  XBT_INFO("Sent!");
+  return 0;
+}
+
+int main(int argc, char *argv[])
+{
+
+  MSG_init(&argc, argv);
+
+  MSG_create_environment("platform.xml");
+
+  MSG_function_register("server", server);
+
+  MSG_function_register("client", client);
+
+  MSG_launch_application("deploy_electric_fence.xml");
+
+  MSG_main();
+
+  return 0;
+
+}
diff --git a/examples/msg/mc/random_test.c b/examples/msg/mc/random_test.c
deleted file mode 100644 (file)
index 8814bdf..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <msg/msg.h>
-#include <simgrid/modelchecker.h>
-
-XBT_LOG_NEW_DEFAULT_CATEGORY(random_test, "Random Test");
-
-int server(int argc, char *argv[]);
-
-int server(int argc, char *argv[])
-{
-  int val;
-  val = MC_random(3, 6);
-  XBT_INFO("val=%d", val);
-  XBT_INFO("OK");
-  return 0;
-}
-
-int main(int argc, char *argv[])
-{
-  MSG_init(&argc, argv);
-
-  MSG_create_environment("platform.xml");
-
-  MSG_function_register("server", server);
-
-//  MSG_function_register("client", client);
-
-  MSG_launch_application("deploy_random_test.xml");
-
-  MSG_main();
-
-  return 0;
-}
index eda1d82..58d9040 100644 (file)
@@ -20,13 +20,13 @@ if(enable_smpi)
   add_executable(mc_bugged2 mc_bugged2.c)
   add_executable(smpi_replay replay/replay.c)
 
-  target_link_libraries(bcbench simgrid smpi )
-  target_link_libraries(mvmul simgrid smpi )
-  target_link_libraries(smpi_traced simgrid smpi )
-  target_link_libraries(smpi_traced_simple simgrid smpi )
-  target_link_libraries(mc_bugged1 simgrid smpi )
-  target_link_libraries(mc_bugged2 simgrid smpi )
-  target_link_libraries(smpi_replay simgrid smpi )
+  target_link_libraries(bcbench simgrid)
+  target_link_libraries(mvmul simgrid)
+  target_link_libraries(smpi_traced simgrid)
+  target_link_libraries(smpi_traced_simple simgrid)
+  target_link_libraries(mc_bugged1 simgrid)
+  target_link_libraries(mc_bugged2 simgrid)
+  target_link_libraries(smpi_replay simgrid)
 
 endif()
 
index 2965048..366f39c 100644 (file)
@@ -8,7 +8,7 @@ if(enable_smpi)
   if(NOT WIN32)
     add_executable(MM_mpi MM_mpi.c 2.5D_MM.c Summa.c Matrix_init.c)
     ### Add definitions for compile
-    target_link_libraries(MM_mpi simgrid pthread smpi)
+    target_link_libraries(MM_mpi simgrid pthread)
   endif()
 endif()
 
index 986a463..0826da7 100644 (file)
@@ -300,7 +300,7 @@ XBT_PUBLIC(msg_error_t)
     MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
                              double timeout);
 
-void MSG_mailbox_set_async(const char *alias);
+XBT_PUBLIC(void) MSG_mailbox_set_async(const char *alias);
 
 
 /************************** Action handling **********************************/
index 49ad142..652b8bc 100644 (file)
@@ -187,6 +187,9 @@ typedef struct s_sg_platf_cluster_cbarg {
   double lat;
   double bb_bw;
   double bb_lat;
+  double loopback_bw;
+  double loopback_lat;
+  double limiter_link;
   const char* router_id;
   e_surf_link_sharing_policy_t sharing_policy;
   e_surf_link_sharing_policy_t bb_sharing_policy;
index 7c900d8..632e77d 100644 (file)
       parameter(MPI_BAND=9)
       parameter(MPI_BOR=10)
       parameter(MPI_BXOR=11)
+      
+      INTEGER MPI_ADDRESS_KIND, MPI_OFFSET_KIND
+      PARAMETER (MPI_ADDRESS_KIND=8)
+      PARAMETER (MPI_OFFSET_KIND=8)
+      
+      INTEGER MPI_MODE_NOPRECEDE
+      PARAMETER (MPI_MODE_NOPRECEDE=8192)
 
       external MPI_INIT, MPI_FINALIZE, MPI_ABORT
       external MPI_COMM_RANK, MPI_COMM_SIZE, MPI_COMM_DUP, MPI_COMM_SPLIT
index aa601ec..b3cfb99 100644 (file)
@@ -401,6 +401,8 @@ MPI_CALL(XBT_PUBLIC(int), MPI_Probe,
 //FIXME: these are not yet implemented
 
 typedef void MPI_Handler_function(MPI_Comm*, int*, ...);
+typedef int MPI_Win;
+typedef int MPI_Info;
 typedef void* MPI_Errhandler;
 typedef int MPI_Copy_function(MPI_Comm oldcomm, int keyval, void* extra_state, void* attribute_val_in,
                               void* attribute_val_out, int* flag);
@@ -464,6 +466,14 @@ MPI_CALL(XBT_PUBLIC(int), MPI_Get_elements, (MPI_Status* status, MPI_Datatype da
 MPI_CALL(XBT_PUBLIC(int), MPI_Dims_create, (int nnodes, int ndims, int* dims));
 MPI_CALL(XBT_PUBLIC(int), MPI_Initialized, (int* flag));
 MPI_CALL(XBT_PUBLIC(int), MPI_Pcontrol, (const int level ));
+MPI_CALL(XBT_PUBLIC(int), MPI_Win_fence,( int assert,  MPI_Win win));
+MPI_CALL(XBT_PUBLIC(int), MPI_Win_free,( MPI_Win* win));
+MPI_CALL(XBT_PUBLIC(int), MPI_Win_create,( void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win));
+MPI_CALL(XBT_PUBLIC(int), MPI_Info_create,( MPI_Info *info));
+MPI_CALL(XBT_PUBLIC(int), MPI_Info_set,( MPI_Info *info, char *key, char *value));
+MPI_CALL(XBT_PUBLIC(int), MPI_Info_free,( MPI_Info *info));
+MPI_CALL(XBT_PUBLIC(int), MPI_Get,( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
+    MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win));
 
 //FIXME: End of all the not yet implemented stuff
 
@@ -508,10 +518,10 @@ XBT_PUBLIC(void*) smpi_shared_set_call(const char* func, const char* input, void
                                          : smpi_shared_set_call(#func, input, func(__VA_ARGS__)))
 
 /* Fortran specific stuff */
-XBT_PUBLIC(int) __attribute__((weak)) smpi_simulated_main__(int argc, char** argv);
+XBT_PUBLIC(int) __attribute__((weak)) smpi_simulated_main_(int argc, char** argv);
 XBT_PUBLIC(int) __attribute__((weak)) MAIN__(void);
 XBT_PUBLIC(int) smpi_main(int (*realmain) (int argc, char *argv[]),int argc, char *argv[]);
-XBT_PUBLIC(void) __attribute__((weak)) user_main__(void);
+XBT_PUBLIC(void) __attribute__((weak)) user_main_(void);
 
 XBT_PUBLIC(int) smpi_process_index(void);
 
index 00bea13..f619d05 100644 (file)
@@ -179,6 +179,8 @@ typedef int AT_surfxml_cluster_bb___bw;
 typedef int AT_surfxml_argument_value;
 #define AU_surfxml_argument_value NULL
 typedef enum { AU_surfxml_link_state, A_surfxml_link_state_ON,A_surfxml_link_state_OFF } AT_surfxml_link_state;
+typedef int AT_surfxml_cluster_loopback___bw;
+#define AU_surfxml_cluster_loopback___bw NULL
 typedef int AT_surfxml_ASroute_gw___src;
 #define AU_surfxml_ASroute_gw___src NULL
 typedef enum { AU_surfxml_AS_routing, A_surfxml_AS_routing_Full,A_surfxml_AS_routing_Floyd,A_surfxml_AS_routing_Dijkstra,A_surfxml_AS_routing_DijkstraCache,A_surfxml_AS_routing_None,A_surfxml_AS_routing_RuleBased,A_surfxml_AS_routing_Vivaldi,A_surfxml_AS_routing_Cluster } AT_surfxml_AS_routing;
@@ -263,6 +265,8 @@ typedef int AT_surfxml_peer_id;
 #define AU_surfxml_peer_id NULL
 typedef int AT_surfxml_cluster_router___id;
 #define AU_surfxml_cluster_router___id NULL
+typedef int AT_surfxml_cluster_loopback___lat;
+#define AU_surfxml_cluster_loopback___lat NULL
 typedef int AT_surfxml_cabinet_radical;
 #define AU_surfxml_cabinet_radical NULL
 typedef enum { AU_surfxml_cluster_sharing___policy, A_surfxml_cluster_sharing___policy_SHARED,A_surfxml_cluster_sharing___policy_FULLDUPLEX,A_surfxml_cluster_sharing___policy_FATPIPE } AT_surfxml_cluster_sharing___policy;
@@ -304,6 +308,8 @@ typedef int AT_surfxml_random_std___deviation;
 #define AU_surfxml_random_std___deviation NULL
 typedef int AT_surfxml_cluster_core;
 #define AU_surfxml_cluster_core NULL
+typedef int AT_surfxml_cluster_limiter___link;
+#define AU_surfxml_cluster_limiter___link NULL
 typedef int AT_surfxml_host_state___file;
 #define AU_surfxml_host_state___file NULL
 typedef int AT_surfxml_route_dst;
@@ -437,6 +443,9 @@ XBT_PUBLIC_DATA(short int) surfxml_argument_value_isset;
 XBT_PUBLIC_DATA(AT_surfxml_link_state) AX_surfxml_link_state;
 #define A_surfxml_link_state AX_surfxml_link_state
 XBT_PUBLIC_DATA(short int) surfxml_link_state_isset;
+XBT_PUBLIC_DATA(AT_surfxml_cluster_loopback___bw) AX_surfxml_cluster_loopback___bw;
+#define A_surfxml_cluster_loopback___bw (surfxml_bufferstack + AX_surfxml_cluster_loopback___bw)
+XBT_PUBLIC_DATA(short int) surfxml_cluster_loopback___bw_isset;
 XBT_PUBLIC_DATA(AT_surfxml_ASroute_gw___src) AX_surfxml_ASroute_gw___src;
 #define A_surfxml_ASroute_gw___src (surfxml_bufferstack + AX_surfxml_ASroute_gw___src)
 XBT_PUBLIC_DATA(short int) surfxml_ASroute_gw___src_isset;
@@ -569,6 +578,9 @@ XBT_PUBLIC_DATA(short int) surfxml_peer_id_isset;
 XBT_PUBLIC_DATA(AT_surfxml_cluster_router___id) AX_surfxml_cluster_router___id;
 #define A_surfxml_cluster_router___id (surfxml_bufferstack + AX_surfxml_cluster_router___id)
 XBT_PUBLIC_DATA(short int) surfxml_cluster_router___id_isset;
+XBT_PUBLIC_DATA(AT_surfxml_cluster_loopback___lat) AX_surfxml_cluster_loopback___lat;
+#define A_surfxml_cluster_loopback___lat (surfxml_bufferstack + AX_surfxml_cluster_loopback___lat)
+XBT_PUBLIC_DATA(short int) surfxml_cluster_loopback___lat_isset;
 XBT_PUBLIC_DATA(AT_surfxml_cabinet_radical) AX_surfxml_cabinet_radical;
 #define A_surfxml_cabinet_radical (surfxml_bufferstack + AX_surfxml_cabinet_radical)
 XBT_PUBLIC_DATA(short int) surfxml_cabinet_radical_isset;
@@ -632,6 +644,9 @@ XBT_PUBLIC_DATA(short int) surfxml_random_std___deviation_isset;
 XBT_PUBLIC_DATA(AT_surfxml_cluster_core) AX_surfxml_cluster_core;
 #define A_surfxml_cluster_core (surfxml_bufferstack + AX_surfxml_cluster_core)
 XBT_PUBLIC_DATA(short int) surfxml_cluster_core_isset;
+XBT_PUBLIC_DATA(AT_surfxml_cluster_limiter___link) AX_surfxml_cluster_limiter___link;
+#define A_surfxml_cluster_limiter___link (surfxml_bufferstack + AX_surfxml_cluster_limiter___link)
+XBT_PUBLIC_DATA(short int) surfxml_cluster_limiter___link_isset;
 XBT_PUBLIC_DATA(AT_surfxml_host_state___file) AX_surfxml_host_state___file;
 #define A_surfxml_host_state___file (surfxml_bufferstack + AX_surfxml_host_state___file)
 XBT_PUBLIC_DATA(short int) surfxml_host_state___file_isset;
index ed7f5c4..d172618 100644 (file)
@@ -19,23 +19,74 @@ void TRACE_smpi_finalize(int rank);
 typedef struct mpi_coll_description {
   const char *name;
   const char *description;
-  voidcoll;
+  void *coll;
 } s_mpi_coll_description_t, *mpi_coll_description_t;
 
-/** \ingroup MPI alltoallcollectives
- *  \brief The list of all available alltoall collectives
+/** \ingroup MPI allgather
+ *  \brief The list of all available allgather collectives
  */
-XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_alltoall_description[];
-int (*mpi_coll_alltoall_fun)(void *, int, MPI_Datatype, void*, int, MPI_Datatype, MPI_Comm);
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_allgather_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_allgather_fun)
+                (void *, int, MPI_Datatype, void *, int, MPI_Datatype,
+                 MPI_Comm));
 
 /** \ingroup MPI allgather
  *  \brief The list of all available allgather collectives
  */
-XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_allgather_description[];
-int (*mpi_coll_allgather_fun)(void *, int, MPI_Datatype, void*, int, MPI_Datatype, MPI_Comm);
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_allgatherv_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_allgatherv_fun)
+                (void *, int, MPI_Datatype, void *, int*, int*, MPI_Datatype,
+                 MPI_Comm));
+
 
-XBT_PUBLIC(void) coll_help(const char *category, s_mpi_coll_description_t * table);
+/** \ingroup MPI allreduce
+ *  \brief The list of all available allgather collectives
+ */
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_allreduce_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_allreduce_fun)
+                (void *sbuf, void *rbuf, int rcount, MPI_Datatype dtype,
+                 MPI_Op op, MPI_Comm comm));
+
+
+/** \ingroup MPI alltoall
+ *  \brief The list of all available alltoall collectives
+ */
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_alltoall_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_alltoall_fun)
+                (void *, int, MPI_Datatype, void *, int, MPI_Datatype,
+                 MPI_Comm));
+
+/** \ingroup MPI alltoallv
+ *  \brief The list of all available alltoallv collectives
+ */
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_alltoallv_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_alltoallv_fun)
+                (void *, int*, int*, MPI_Datatype, void *, int*, int*, MPI_Datatype,
+                 MPI_Comm));
+
+
+/** \ingroup MPI bcast
+ *  \brief The list of all available bcast collectives
+ */
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_bcast_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_bcast_fun)
+                (void *buf, int count, MPI_Datatype datatype, int root,
+                 MPI_Comm com));
+
+
+/** \ingroup MPI reduce
+ *  \brief The list of all available reduce collectives
+ */
+XBT_PUBLIC_DATA(s_mpi_coll_description_t) mpi_coll_reduce_description[];
+XBT_PUBLIC_DATA(int (*mpi_coll_reduce_fun)
+                (void *buf, void *rbuf, int count, MPI_Datatype datatype,
+                 MPI_Op op, int root, MPI_Comm comm));
+
+
+XBT_PUBLIC(void) coll_help(const char *category,
+                           s_mpi_coll_description_t * table);
 XBT_PUBLIC(int) find_coll_description(s_mpi_coll_description_t * table,
-                           const char *name);
+                                      const char *name);
+
 
 #endif                          /* _SMPI_INTERFAC_H */
index 0092095..ab31a17 100644 (file)
@@ -12,6 +12,8 @@ typedef struct s_surf_parsing_link_up_down *surf_parsing_link_up_down_t;
 typedef struct s_surf_parsing_link_up_down {
   void* link_up;
   void* link_down;
+  void* limiter_link;
+  void* loopback_link;
 } s_surf_parsing_link_up_down_t;
 
 #endif /* SURFXML_PARSE_VALUES_H_ */
index f41aad7..7d61fef 100644 (file)
@@ -19,6 +19,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY (instr_config, instr, "Configuration");
 #define OPT_TRACING_SMPI          "tracing/smpi"
 #define OPT_TRACING_SMPI_GROUP    "tracing/smpi/group"
 #define OPT_TRACING_SMPI_COMPUTING "tracing/smpi/computing"
+#define OPT_TRACING_SMPI_INTERNALS "tracing/smpi/internals"
 #define OPT_TRACING_CATEGORIZED   "tracing/categorized"
 #define OPT_TRACING_UNCATEGORIZED "tracing/uncategorized"
 #define OPT_TRACING_MSG_PROCESS   "tracing/msg/process"
@@ -41,6 +42,7 @@ static int trace_platform_topology;
 static int trace_smpi_enabled;
 static int trace_smpi_grouped;
 static int trace_smpi_computing;
+static int trace_view_internals;
 static int trace_categorized;
 static int trace_uncategorized;
 static int trace_msg_process_enabled;
@@ -65,6 +67,7 @@ static void TRACE_getopts(void)
   trace_smpi_enabled = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_SMPI);
   trace_smpi_grouped = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_SMPI_GROUP);
   trace_smpi_computing = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_SMPI_COMPUTING);
+  trace_view_internals = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_SMPI_INTERNALS);
   trace_categorized = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_CATEGORIZED);
   trace_uncategorized = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_UNCATEGORIZED);
   trace_msg_process_enabled = xbt_cfg_get_int(_sg_cfg_set, OPT_TRACING_MSG_PROCESS);
@@ -225,6 +228,10 @@ int TRACE_smpi_is_computing(void)
   return trace_smpi_computing;
 }
 
+int TRACE_smpi_view_internals(void)
+{
+  return trace_view_internals;
+}
 
 int TRACE_categorized (void)
 {
@@ -352,6 +359,13 @@ void TRACE_global_init(int *argc, char **argv)
                    xbt_cfgelm_int, &default_tracing_smpi_computing, 0, 1,
                    NULL, NULL);
 
+  /* smpi internals */
+  int default_tracing_smpi_internals = 0;
+  xbt_cfg_register(&_sg_cfg_set, OPT_TRACING_SMPI_INTERNALS,
+                   "View internal messages sent by Collective communications in SMPI",
+                   xbt_cfgelm_int, &default_tracing_smpi_internals, 0, 1,
+                   NULL, NULL);
+
   /* tracing categorized resource utilization traces */
   int default_tracing_categorized = 0;
   xbt_cfg_register(&_sg_cfg_set, OPT_TRACING_CATEGORIZED,
@@ -506,6 +520,9 @@ void TRACE_help (int detailed)
       "  This option aims at tracing computations in the application, outside SMPI\n"
       "  to allow further study of simulated or real computation time",
       detailed);
+  print_line (OPT_TRACING_SMPI_INTERNALS, "Generates tracing events corresponding",
+      "  to point-to-point messages sent by collective communications",
+      detailed);
   print_line (OPT_TRACING_MSG_PROCESS, "Trace processes behavior (MSG)",
       "  This option only has effect if this simulator is MSG-based. It traces the\n"
       "  behavior of all categorized MSG processes, grouping them by hosts. This option\n"
index 07f7dce..24f2af3 100644 (file)
@@ -161,6 +161,7 @@ void instr_resume_tracing (void);
 XBT_PUBLIC(int) TRACE_smpi_is_enabled(void);
 XBT_PUBLIC(int) TRACE_smpi_is_grouped(void);
 XBT_PUBLIC(int) TRACE_smpi_is_computing(void);
+XBT_PUBLIC(int) TRACE_smpi_view_internals(void);
 
 /* from resource_utilization.c */
 void TRACE_surf_host_set_utilization(const char *resource,
index 7388684..da1efaa 100644 (file)
@@ -72,33 +72,17 @@ static int compare_global_variables(int region_type, void *d1, void *d2){ /* reg
     }
     i = 0;
     while(i < current_var->size){
-      if(memcmp((char*)d1 + offset + i, (char*)d2 + offset + i, 1) != 0){
+      if(memcmp((char *)d1 + offset + i, (char *)d2 + offset + i, 1) != 0){ 
         pointer_align = (i / sizeof(void*)) * sizeof(void*); 
         addr_pointed1 = *((void **)((char *)d1 + offset + pointer_align));
         addr_pointed2 = *((void **)((char *)d2 + offset + pointer_align));
         if((addr_pointed1 > plt_start && addr_pointed1 < plt_end) || (addr_pointed2 > plt_start && addr_pointed2 < plt_end)){
-          break;
-        }else{
-          if((addr_pointed1 > std_heap) && ((char *)addr_pointed1 < (char *)std_heap + STD_HEAP_SIZE) 
-             && (addr_pointed2 > std_heap) && ((char *)addr_pointed2 < (char *)std_heap + STD_HEAP_SIZE)){
-            res_compare = compare_area(addr_pointed1, addr_pointed2, NULL);
-            if(res_compare == 1){
-              #ifdef MC_VERBOSE
-              if(region_type == 2)
-                XBT_VERB("Different global variable in binary : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
-              else
-                XBT_VERB("Different global variable in libsimgrid : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
-              #endif
-              #ifdef MC_DEBUG
-                if(region_type == 2)
-                  XBT_DEBUG("Different global variable in binary : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
-                else
-                  XBT_DEBUG("Different global variable in libsimgrid : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
-              #endif
-                XBT_INFO("Different global variable (%p, %p) : %s at addresses %p - %p (size = %zu)", current_var->address, addr_pointed1, current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
-              return 1;
-            }
-          }else{
+          i = pointer_align + sizeof(void*);
+          continue;
+        }else if((addr_pointed1 > std_heap) && ((char *)addr_pointed1 < (char *)std_heap + STD_HEAP_SIZE) 
+                && (addr_pointed2 > std_heap) && ((char *)addr_pointed2 < (char *)std_heap + STD_HEAP_SIZE)){
+          res_compare = compare_area(addr_pointed1, addr_pointed2, NULL);
+          if(res_compare == 1){
             #ifdef MC_VERBOSE
               if(region_type == 2)
                 XBT_VERB("Different global variable in binary : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
@@ -111,12 +95,26 @@ static int compare_global_variables(int region_type, void *d1, void *d2){ /* reg
               else
                 XBT_DEBUG("Different global variable in libsimgrid : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
             #endif
-              XBT_INFO("Different global variable (%p, %p) : %s at addresses %p - %p (size = %zu)", current_var->address, addr_pointed1, current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
             return 1;
           }
-              
-        }
-      } 
+          i = pointer_align + sizeof(void*);
+          continue;
+        }else{
+          #ifdef MC_VERBOSE
+            if(region_type == 2)
+              XBT_VERB("Different global variable in binary : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
+            else
+              XBT_VERB("Different global variable in libsimgrid : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
+          #endif
+          #ifdef MC_DEBUG
+            if(region_type == 2)
+              XBT_DEBUG("Different global variable in binary : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
+            else
+              XBT_DEBUG("Different global variable in libsimgrid : %s at addresses %p - %p (size = %zu)", current_var->name, (char *)d1+offset, (char *)d2+offset, current_var->size);
+          #endif
+          return 1;
+        }              
+      }
       i++;
     }
   }
@@ -409,49 +407,48 @@ int snapshot_compare(mc_snapshot_t s1, mc_snapshot_t s2){
     xbt_os_timer_start(timer);
   #endif
 
-    /* Stacks comparison */
-    unsigned int  cursor = 0;
-    int diff_local = 0;
-    is_diff = 0;
+  /* Stacks comparison */
+  unsigned int  cursor = 0;
+  int diff_local = 0;
+  is_diff = 0;
     
-    while(cursor < xbt_dynar_length(s1->stacks)){
-      diff_local = compare_local_variables(((mc_snapshot_stack_t)xbt_dynar_get_as(s1->stacks, cursor, mc_snapshot_stack_t))->local_variables->data, ((mc_snapshot_stack_t)xbt_dynar_get_as(s2->stacks, cursor, mc_snapshot_stack_t))->local_variables->data);
-      if(diff_local > 0){
-        #ifdef MC_DEBUG
-          if(is_diff == 0){
-            xbt_os_timer_stop(timer);
-            mc_comp_times->stacks_comparison_time = xbt_os_timer_elapsed(timer); 
-          }
-          XBT_DEBUG("Different local variables between stacks %d", cursor + 1);
-          errors++;
-          is_diff = 1;
-        #else
+  while(cursor < xbt_dynar_length(s1->stacks)){
+    diff_local = compare_local_variables(((mc_snapshot_stack_t)xbt_dynar_get_as(s1->stacks, cursor, mc_snapshot_stack_t))->local_variables->data, ((mc_snapshot_stack_t)xbt_dynar_get_as(s2->stacks, cursor, mc_snapshot_stack_t))->local_variables->data);
+    if(diff_local > 0){
+      #ifdef MC_DEBUG
+        if(is_diff == 0){
+          xbt_os_timer_stop(timer);
+          mc_comp_times->stacks_comparison_time = xbt_os_timer_elapsed(timer); 
+        }
+        XBT_DEBUG("Different local variables between stacks %d", cursor + 1);
+        errors++;
+        is_diff = 1;
+      #else
         
-          #ifdef MC_VERBOSE
-            XBT_VERB("Different local variables between stacks %d", cursor + 1);
-          #endif
-          
-            reset_heap_information();
-            xbt_os_timer_free(timer);
-            xbt_os_timer_stop(global_timer);
-            mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
-            xbt_os_timer_free(global_timer);
-            
-            if(!raw_mem)
-              MC_UNSET_RAW_MEM;
-            
-            return 1;
+        #ifdef MC_VERBOSE
+          XBT_VERB("Different local variables between stacks %d", cursor + 1);
         #endif
-      }
-      cursor++;
+          
+        reset_heap_information();
+        xbt_os_timer_free(timer);
+        xbt_os_timer_stop(global_timer);
+        mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
+        xbt_os_timer_free(global_timer);
+        
+        if(!raw_mem)
+          MC_UNSET_RAW_MEM;
+        
+        return 1;
+      #endif
     }
+    cursor++;
+  }
     
-    #ifdef MC_DEBUG
-      xbt_os_timer_start(timer);
-    #endif
+  #ifdef MC_DEBUG
+    xbt_os_timer_start(timer);
+  #endif
 
   /* Compare heap */
   if(mmalloc_compare_heap((xbt_mheap_t)s1->regions[0]->data, (xbt_mheap_t)s2->regions[0]->data)){
 
     #ifdef MC_DEBUG
@@ -572,7 +569,7 @@ static int compare_local_variables(char *s1, char *s2){
             continue;
           }else {
             #ifdef MC_VERBOSE
-              XBT_VERB("Different local variable : %s at addresses %p - %p", var_name, addr1, addr2);
+              XBT_VERB("Different local variable : %s at addresses %p - %p in frame %s", var_name, addr1, addr2, frame_name1);
             #endif
             #ifdef MC_DEBUG
               XBT_DEBUG("Different local variable : %s at addresses %p - %p", var_name, addr1, addr2);
@@ -595,7 +592,7 @@ static int compare_local_variables(char *s1, char *s2){
             continue;
           }else {
             #ifdef MC_VERBOSE
-              XBT_VERB("Different local variable : %s (%s - %s)", var_name, xbt_dynar_get_as(s_tokens1, 1, char *), xbt_dynar_get_as(s_tokens2, 1, char *));
+              XBT_VERB("Different local variable : %s (%s - %s) in frame %s", var_name, xbt_dynar_get_as(s_tokens1, 1, char *), xbt_dynar_get_as(s_tokens2, 1, char *), frame_name1);
             #endif
             #ifdef MC_DEBUG
               XBT_DEBUG("Different local variable : %s (%s - %s)", var_name, xbt_dynar_get_as(s_tokens1, 1, char *), xbt_dynar_get_as(s_tokens2, 1, char *));
index a97440a..7c5b998 100644 (file)
@@ -247,14 +247,14 @@ void MC_dpor(void)
 {
 
   char *req_str;
-  int value, value2;
-  smx_simcall_t req = NULL, prev_req = NULL, req2 = NULL;
-  s_smx_simcall_t req3;
+  int value;
+  smx_simcall_t req = NULL, prev_req = NULL;
   mc_state_t state = NULL, prev_state = NULL, next_state = NULL, restore_state=NULL;
   smx_process_t process = NULL;
   xbt_fifo_item_t item = NULL;
   int pos;
   int visited_state;
+  int enabled = 0, max_depth_reached = 0;
 
   while (xbt_fifo_size(mc_stack_safety) > 0) {
 
@@ -282,7 +282,8 @@ void MC_dpor(void)
         xbt_free(req_str);
       }
         
-      req_str = MC_request_get_dot_output(req, value);
+      if(dot_output != NULL)
+        req_str = MC_request_get_dot_output(req, value);
 
       MC_state_set_executed_request(state, req, value);
       mc_stats->executed_transitions++;
@@ -293,8 +294,6 @@ void MC_dpor(void)
       xbt_free(key);
       MC_UNSET_RAW_MEM;
 
-      MC_state_set_executed_request(state, req, value);
-
       /* Answer the request */
       SIMIX_simcall_pre(req, value); /* After this call req is no longer usefull */
 
@@ -347,24 +346,64 @@ void MC_dpor(void)
 
       MC_UNSET_RAW_MEM;
 
-      xbt_free(req_str);
+      if(dot_output != NULL)
+        xbt_free(req_str);
 
       /* Let's loop again */
 
       /* The interleave set is empty or the maximum depth is reached, let's back-track */
     } else {
 
-      if(xbt_fifo_size(mc_stack_safety) == _sg_mc_max_depth)  
+      if(xbt_fifo_size(mc_stack_safety) > _sg_mc_max_depth){  
+
         XBT_WARN("/!\\ Max depth reached ! /!\\ ");
-      else
+
+        /* Interleave enabled processes in the state in which they have been enabled for the first time */
+        xbt_swag_foreach(process, simix_global->process_list){
+          if(MC_process_is_enabled(process)){
+            char *key = bprintf("%lu", process->pid);
+            enabled = (int)strtoul(xbt_dict_get_or_null(first_enabled_state, key), 0, 10);
+            xbt_free(key);
+            mc_state_t state_test = NULL;
+            xbt_fifo_item_t item = NULL;
+            int cursor = xbt_fifo_size(mc_stack_safety);
+            xbt_fifo_foreach(mc_stack_safety, item, state_test, mc_state_t){
+              if(cursor-- == enabled){ 
+                if(!MC_state_process_is_done(state_test, process)){ 
+                  MC_state_interleave_process(state_test, process);
+                  break;
+                }
+              }
+            } 
+          }
+        }
+
+        if(MC_state_interleave_size(state) > 0){
+          max_depth_reached = 1;
+        }else{
+          /* Trash the current state, no longer needed */
+          MC_SET_RAW_MEM;
+          xbt_fifo_shift(mc_stack_safety);
+          MC_state_delete(state);
+          MC_UNSET_RAW_MEM;
+
+          max_depth_reached = 0;
+        }
+        
+
+      }else{
+
         XBT_DEBUG("There are no more processes to interleave.");
 
-      /* Trash the current state, no longer needed */
-      MC_SET_RAW_MEM;
-      xbt_fifo_shift(mc_stack_safety);
-      MC_state_delete(state);
-      MC_UNSET_RAW_MEM;
+        /* Trash the current state, no longer needed */
+        MC_SET_RAW_MEM;
+        xbt_fifo_shift(mc_stack_safety);
+        MC_state_delete(state);
+        MC_UNSET_RAW_MEM;
 
+        max_depth_reached = 0;
+      }
+      
       /* Check for deadlocks */
       if(MC_deadlock_check()){
         MC_show_deadlock(NULL);
@@ -381,33 +420,11 @@ void MC_dpor(void)
       
       while ((state = xbt_fifo_shift(mc_stack_safety)) != NULL) {
         if(mc_reduce_kind != e_mc_reduce_none){
-          req = MC_state_get_internal_request(state);
-          /* If max_depth reached, check only for the last state if the request that has generated
-             it, depends on any other processes still enabled when max_depth reached */
-          if(xbt_fifo_size(mc_stack_safety) == _sg_mc_max_depth - 1){
-            req3 = *req;
-            xbt_swag_foreach(process, simix_global->process_list){
-              if(MC_process_is_enabled(process) && !MC_state_process_is_done(state, process)){
-                MC_state_interleave_process(state, process);
-                req2 = MC_state_get_request(state, &value2);
-                MC_state_set_executed_request(state, req2, value2);
-                req2 = MC_state_get_internal_request(state);
-                if(MC_request_depend(&req3, req2)){
-                  if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
-                    XBT_DEBUG("Dependent Transitions:");
-                    req_str = MC_request_to_string(&req3, value);
-                    XBT_DEBUG("%s (state=%p)", req_str, state);
-                    xbt_free(req_str);
-                    req_str = MC_request_to_string(req2, value);
-                    XBT_DEBUG("%s (state=%p)", req_str, state);
-                    xbt_free(req_str);              
-                  } 
-                  MC_state_interleave_process(state, process);
-                  break;
-                }
-              }
-            }
+          if((xbt_fifo_size(mc_stack_safety) == _sg_mc_max_depth) && max_depth_reached){
+            req = MC_state_get_request(state, &value);
+            MC_state_set_executed_request(state, req, value);
           }
+          req = MC_state_get_internal_request(state);
           xbt_fifo_foreach(mc_stack_safety, item, prev_state, mc_state_t) {
             if(MC_request_depend(req, MC_state_get_internal_request(prev_state))){
               if(XBT_LOG_ISENABLED(mc_dpor, xbt_log_priority_debug)){
@@ -438,8 +455,9 @@ void MC_dpor(void)
           }
         }
              
-        if (MC_state_interleave_size(state)) {
+        if (MC_state_interleave_size(state) && xbt_fifo_size(mc_stack_safety) < _sg_mc_max_depth) {
           /* We found a back-tracking point, let's loop */
+          XBT_DEBUG("Back-tracking to depth %d", xbt_fifo_size(mc_stack_safety) + 1);
           if(_sg_mc_checkpoint){
             if(state->system_state != NULL){
               MC_restore_snapshot(state->system_state);
index 562eb37..430da06 100644 (file)
@@ -138,9 +138,6 @@ void MC_do_the_modelcheck_for_real() {
   mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
   MC_UNSET_RAW_MEM;
   
-  if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
-    MC_init_dot_output();
-
   if (!_sg_mc_property_file || _sg_mc_property_file[0]=='\0') {
     if (mc_reduce_kind==e_mc_reduce_unset)
       mc_reduce_kind=e_mc_reduce_dpor;
@@ -213,6 +210,9 @@ void MC_init(){
   MC_ignore_stack("next_context", "smx_ctx_sysv_suspend_serial");
   MC_ignore_stack("i", "smx_ctx_sysv_suspend_serial");
 
+  /* Ignore local variable about time used for tracing */
+  MC_ignore_stack("start_time", "*"); 
+
   MC_ignore_data_bss(&mc_comp_times, sizeof(mc_comp_times));
   MC_ignore_data_bss(&mc_snapshot_comparison_time, sizeof(mc_snapshot_comparison_time)); 
   MC_ignore_data_bss(&mc_time, sizeof(mc_time));
@@ -269,6 +269,9 @@ void MC_modelcheck_safety(void)
   /* Create exploration stack */
   mc_stack_safety = xbt_fifo_new();
 
+  if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
+    MC_init_dot_output();
+
   MC_UNSET_RAW_MEM;
 
   if(_sg_mc_visited > 0){
@@ -320,6 +323,9 @@ void MC_modelcheck_liveness(){
   /* Create the initial state */
   initial_state_liveness = xbt_new0(s_mc_global_t, 1);
 
+  if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
+    MC_init_dot_output();
+  
   MC_UNSET_RAW_MEM;
 
   MC_ddfs_init();
@@ -336,13 +342,6 @@ void MC_modelcheck_liveness(){
 
 void MC_exit(void)
 {
-  MC_SET_RAW_MEM;
-  if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
-    fprintf(dot_output, "}\n");
-    fclose(dot_output);
-  }
-  MC_UNSET_RAW_MEM;
-
   xbt_free(mc_time);
   MC_memory_exit();
   xbt_abort();
@@ -738,6 +737,12 @@ void MC_print_statistics(mc_stats_t stats)
     XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
   }
   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
+  MC_SET_RAW_MEM;
+  if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
+    fprintf(dot_output, "}\n");
+    fclose(dot_output);
+  }
+  MC_UNSET_RAW_MEM;
 }
 
 void MC_assert(int prop)
@@ -844,10 +849,10 @@ void MC_ignore_heap(void *address, size_t size){
   
   if(((xbt_mheap_t)std_heap)->heapinfo[region->block].type == 0){
     region->fragment = -1;
-    ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore = 1;
+    ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore++;
   }else{
     region->fragment = ((uintptr_t) (ADDR2UINT (address) % (BLOCKSIZE))) >> ((xbt_mheap_t)std_heap)->heapinfo[region->block].type;
-    ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment] = 1;
+    ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
   }
   
   if(mc_heap_comparison_ignore == NULL){
index 362e331..424929e 100644 (file)
@@ -605,6 +605,7 @@ void MC_ddfs(int search_cycle){
   xbt_automaton_transition_t transition_succ;
   unsigned int cursor = 0;
   int res;
+  int reached_num;
 
   mc_pair_t next_pair = NULL;
   mc_pair_t pair_succ;
@@ -694,9 +695,9 @@ void MC_ddfs(int search_cycle){
 
             if((pair_succ->automaton_state->type == 1) || (pair_succ->automaton_state->type == 2)){ 
           
-              if(is_reached_acceptance_pair(pair_succ->num, pair_succ->automaton_state) != -1){
+              if((reached_num = is_reached_acceptance_pair(pair_succ->num, pair_succ->automaton_state)) != -1){
         
-                XBT_INFO("Next pair (depth = %d, %u interleave) already reached !", xbt_fifo_size(mc_stack_liveness) + 1, MC_state_interleave_size(pair_succ->graph_state));
+                XBT_INFO("Next pair (depth = %d, %u interleave) already reached (equal to state %d) !", xbt_fifo_size(mc_stack_liveness) + 1, MC_state_interleave_size(pair_succ->graph_state), reached_num);
 
                 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
                 XBT_INFO("|             ACCEPTANCE CYCLE            |");
@@ -845,9 +846,9 @@ void MC_ddfs(int search_cycle){
 
           if((pair_succ->automaton_state->type == 1) || (pair_succ->automaton_state->type == 2)){ 
 
-            if(is_reached_acceptance_pair(pair_succ->num, pair_succ->automaton_state) != -1){
+            if((reached_num = is_reached_acceptance_pair(pair_succ->num, pair_succ->automaton_state)) != -1){
            
-              XBT_INFO("Next pair (depth = %d) already reached !", xbt_fifo_size(mc_stack_liveness) + 1);
+              XBT_INFO("Next pair (depth = %d) already reached (equal to state %d)!", xbt_fifo_size(mc_stack_liveness) + 1, reached_num);
         
               XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
               XBT_INFO("|             ACCEPTANCE CYCLE            |");
index c25a0bc..95b4b9e 100644 (file)
@@ -24,7 +24,7 @@ int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2) {
   if(r1->call == SIMCALL_COMM_IRECV && r2->call == SIMCALL_COMM_ISEND)
     return FALSE;
 
-  /*if(   (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
+  if(   (r1->call == SIMCALL_COMM_ISEND || r1->call == SIMCALL_COMM_IRECV)
         &&  r2->call == SIMCALL_COMM_WAIT){
 
     if(simcall_comm_wait__get__comm(r2)->comm.rdv == NULL)
@@ -32,13 +32,13 @@ int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2) {
 
     smx_rdv_t rdv = r1->call == SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r1) : simcall_comm_irecv__get__rdv(r1);
 
-    if(simcall_comm_wait__get__comm(r2)->comm.rdv != rdv)
+    if((simcall_comm_wait__get__comm(r2)->comm.rdv != rdv) && (simcall_comm_wait__get__timeout(r2) <= 0))
       return FALSE;
 
-    if(simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND && r1->call == SIMCALL_COMM_ISEND)
+    if((simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_SEND) && (r1->call == SIMCALL_COMM_ISEND) && (simcall_comm_wait__get__timeout(r2) <= 0))
       return FALSE;
 
-    if(simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE && r1->call == SIMCALL_COMM_IRECV)
+    if((simcall_comm_wait__get__comm(r2)->comm.type == SIMIX_COMM_RECEIVE) && (r1->call == SIMCALL_COMM_IRECV) && (simcall_comm_wait__get__timeout(r2) <= 0))
       return FALSE;
   }
 
@@ -50,15 +50,15 @@ int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2) {
 
     smx_rdv_t rdv = r2->call == SIMCALL_COMM_ISEND ? simcall_comm_isend__get__rdv(r2) : simcall_comm_irecv__get__rdv(r2);
 
-    if(simcall_comm_wait__get__comm(r1)->comm.rdv != rdv)
+    if((simcall_comm_wait__get__comm(r1)->comm.rdv != rdv) && (simcall_comm_wait__get__timeout(r1) <= 0))
       return FALSE;
 
-    if(simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND && r2->call == SIMCALL_COMM_ISEND)
+    if((simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_SEND) && (r2->call == SIMCALL_COMM_ISEND) && (simcall_comm_wait__get__timeout(r1) <= 0))
       return FALSE;
 
-    if(simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE && r2->call == SIMCALL_COMM_IRECV)
+    if((simcall_comm_wait__get__comm(r1)->comm.type == SIMIX_COMM_RECEIVE) && (r2->call == SIMCALL_COMM_IRECV) && (simcall_comm_wait__get__timeout(r1) <= 0))
       return FALSE;
-      }*/
+  }
 
   /* FIXME: the following rule assumes that the result of the
    * isend/irecv call is not stored in a buffer used in the
@@ -195,7 +195,7 @@ char *MC_request_to_string(smx_simcall_t req, int value)
     if(value == -1){
       type = xbt_strdup("WaitTimeout");
       p = pointer_to_string(act);
-      args = bprintf("comm=%p", p);
+      args = bprintf("comm=%s", p);
     }else{
       type = xbt_strdup("Wait");
       p = pointer_to_string(act);
index b431523..b0e84a6 100644 (file)
@@ -32,6 +32,8 @@ memory_map_t get_memory_map(void)
   xbt_assert(fp,
               "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug.");
 
+  setbuf(fp, NULL);
+
   ret = xbt_new0(s_memory_map_t, 1);
 
   /* Read one line at the time, parse it and add it to the memory map to be returned */
index 9f3f379..f587002 100644 (file)
@@ -77,7 +77,7 @@ XBT_PUBLIC(int) MSG_mailbox_is_empty(msg_mailbox_t mailbox);
  * \param alias    The alias of the mailbox to modify.
  *
  */
-void MSG_mailbox_set_async(const char *alias);
+XBT_PUBLIC(void) MSG_mailbox_set_async(const char *alias);
 
 /*! \brief MSG_mailbox_get_head - get the task at the head of a mailbox.
  *
index 28fcdf7..63f1a02 100644 (file)
@@ -226,8 +226,9 @@ static void _sg_cfg_cb__weight_S(const char *name, int pos)
   sg_weight_S_parameter = xbt_cfg_get_double(_sg_cfg_set, name);
 }
 
+#ifdef HAVE_SMPI
 /* callback of the mpi collectives */
-static void _sg_cfg_cb__coll(char *category,
+static void _sg_cfg_cb__coll(const char *category,
                             s_mpi_coll_description_t * table,
                             const char *name, int pos)
 {
@@ -246,14 +247,33 @@ static void _sg_cfg_cb__coll(char *category,
   /* New Module missing */
   find_coll_description(table, val);
 }
+static void _sg_cfg_cb__coll_allgather(const char *name, int pos){
+  _sg_cfg_cb__coll("allgather", mpi_coll_allgather_description, name, pos);
+}
+static void _sg_cfg_cb__coll_allgatherv(const char *name, int pos){
+  _sg_cfg_cb__coll("allgatherv", mpi_coll_allgatherv_description, name, pos);
+}
+static void _sg_cfg_cb__coll_allreduce(const char *name, int pos)
+{
+  _sg_cfg_cb__coll("allreduce", mpi_coll_allreduce_description, name, pos);
+}
 static void _sg_cfg_cb__coll_alltoall(const char *name, int pos)
 {
   _sg_cfg_cb__coll("alltoall", mpi_coll_alltoall_description, name, pos);  
 }
-static void _sg_cfg_cb__coll_allgather(const char *name, int pos){
-  _sg_cfg_cb__coll("allgather", mpi_coll_allgather_description, name, pos);
+static void _sg_cfg_cb__coll_alltoallv(const char *name, int pos)
+{
+  _sg_cfg_cb__coll("alltoallv", mpi_coll_alltoallv_description, name, pos);  
 }
-
+static void _sg_cfg_cb__coll_bcast(const char *name, int pos)
+{
+  _sg_cfg_cb__coll("bcast", mpi_coll_bcast_description, name, pos);  
+}
+static void _sg_cfg_cb__coll_reduce(const char *name, int pos)
+{
+  _sg_cfg_cb__coll("reduce", mpi_coll_reduce_description, name, pos);  
+}
+#endif
 
 /* callback of the inclusion path */
 static void _sg_cfg_cb__surf_path(const char *name, int pos)
@@ -674,7 +694,7 @@ void sg_config_init(int *argc, char **argv)
     xbt_cfg_setdefault_string(_sg_cfg_set, "ns3/TcpModel", "default");
 #endif
 
-//SMPI
+#ifdef HAVE_SMPI
     double default_reference_speed = 20000.0;
     xbt_cfg_register(&_sg_cfg_set, "smpi/running_power",
                      "Power of the host running the simulation (in flop/s). Used to bench the operations.",
@@ -740,19 +760,49 @@ void sg_config_init(int *argc, char **argv)
                      NULL);
     xbt_cfg_setdefault_string(_sg_cfg_set, "smpi/or", "1:0:0:0:0");
 
-    default_value = xbt_strdup("ompi");    
+    default_value = xbt_strdup("default");
+    xbt_cfg_register(&_sg_cfg_set, "smpi/allgather",
+                    "Which collective to use for allgather",
+                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_allgather,
+                    NULL);
+
+    default_value = xbt_strdup("default");
+    xbt_cfg_register(&_sg_cfg_set, "smpi/allgatherv",
+                    "Which collective to use for allgatherv",
+                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_allgatherv,
+                    NULL);
+
+    default_value = xbt_strdup("default");
+    xbt_cfg_register(&_sg_cfg_set, "smpi/allreduce",
+                    "Which collective to use for allreduce",
+                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_allreduce,
+                    NULL);
+
+    default_value = xbt_strdup("ompi");
     xbt_cfg_register(&_sg_cfg_set, "smpi/alltoall",
                     "Which collective to use for alltoall",
                     xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_alltoall,
                     NULL);
 
-    default_value = xbt_strdup("default");    
-    xbt_cfg_register(&_sg_cfg_set, "smpi/allgather",
-                    "Which collective to use for allgather",
-                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_allgather,
+    default_value = xbt_strdup("default");
+    xbt_cfg_register(&_sg_cfg_set, "smpi/alltoallv",
+                    "Which collective to use for alltoallv",
+                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_alltoallv,
                     NULL);
-    //END SMPI
 
+    default_value = xbt_strdup("default");
+    xbt_cfg_register(&_sg_cfg_set, "smpi/bcast",
+                    "Which collective to use for bcast",
+                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_bcast,
+                    NULL);
+
+
+    default_value = xbt_strdup("default");
+    xbt_cfg_register(&_sg_cfg_set, "smpi/reduce",
+                    "Which collective to use for reduce",
+                    xbt_cfgelm_string, &default_value, 1, 1, &_sg_cfg_cb__coll_reduce,
+                    NULL);
+#endif // HAVE_SMPI
 
     if (!surf_path) {
       /* retrieves the current directory of the        current process */
index 97b85eb..6fe2029 100644 (file)
@@ -1,39 +1,30 @@
-Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
-All rights reserved.
+Copyright(c) 2006, Ahmad Faraj & Xin Yuan, All rights reserved.Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice,
+*Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
-
-  * Redistributions in binary form must reproduce the above copyright notice,
+    * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
-    and/or other materials provided with the distribution.
-
-  * Neither the name of the Florida State University nor the names of its
+    and / or other materials provided with the distribution.
+    * Neither the name of the Florida State University nor the names of its
     contributors may be used to endorse or promote products derived from this
-    software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  ***************************************************************************
-  *     Any results obtained from executing this software require the       *
-  *     acknowledgment and citation of the software and its owners.         *
-  *     The full citation is given below:                                   *
-  *                                                                         *
-  *     A. Faraj, X. Yuan, and D. Lowenthal. "STAR-MPI: Self Tuned Adaptive *
-  *     Routines for MPI Collective Operations." The 20th ACM International *
-  *     Conference on Supercomputing (ICS), Queensland, Australia           *
-  *     June 28-July 1, 2006.                                               *
-  ***************************************************************************
-
+    software without specific prior written permission.THIS SOFTWARE IS PROVIDED
+    BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
+                             PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+                             LOSS OF USE, DATA, OR PROFITS;
+                             OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON
+    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+    ***************************************************************************
+    *Any results obtained from executing this software require the *
+    *acknowledgment and citation of the software and its owners. *
+    *The full citation is given below:****A.Faraj, X.Yuan, and D.Lowenthal."STAR-MPI: Self Tuned Adaptive *
+  *     Routines for MPI Collective Operations." The 20 th ACM International * *Conference on Supercomputing(ICS), Queensland, Australia * *June 28 - July 1, 2006. * ***************************************************************************
diff --git a/src/smpi/colls/allgather-2dmesh.c b/src/smpi/colls/allgather-2dmesh.c
new file mode 100644 (file)
index 0000000..b5f5042
--- /dev/null
@@ -0,0 +1,186 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+
+ * Function: is_2dmesh
+
+ * Return: int
+
+ * Inputs:
+     num: the number of processors in a communicator
+     i: x dimension
+     j: y dimension
+
+ * Descp: takes a number and tries to find a factoring of x, y mesh out of it
+
+ * Auther: Ahmad Faraj
+ ****************************************************************************/
+#ifndef TWOD
+#define TWOD
+static int is_2dmesh(int num, int *i, int *j)
+{
+  int x, max = num / 2;
+  x = sqrt(num);
+
+  while (x <= max) {
+    if ((num % x) == 0) {
+      *i = x;
+      *j = num / x;
+
+      if (*i > *j) {
+        x = *i;
+        *i = *j;
+        *j = x;
+      }
+
+      return 1;
+    }
+    x++;
+  }
+  return 0;
+}
+#endif
+/*****************************************************************************
+ * Function: allgather_2dmesh_shoot
+ * return: int
+ * send_buff: send input buffer
+ * send_count: number of elements to send
+ * send_type: data type of elements being sent
+ * recv_buff: receive output buffer
+ * recv_count: number of elements to received
+ * recv_type: data type of elements being received
+ * comm: communication
+ * Descrp: Function realizes the allgather operation using the 2dmesh
+ * algorithm. Allgather ommunication occurs first in the x dimension then in
+ * the y dimension.  The communication in each dimension follows 
+ * "simple"
+ * Auther: Ahmad Faraj
+****************************************************************************/
+int
+smpi_coll_tuned_allgather_2dmesh(void *send_buff, int send_count, MPI_Datatype
+                                 send_type, void *recv_buff, int recv_count,
+                                 MPI_Datatype recv_type, MPI_Comm comm)
+{
+  MPI_Request *req, *req_ptr;
+  MPI_Aint extent;
+
+  int i, src, dst, rank, num_procs;
+  int X, Y, send_offset, recv_offset;
+  int my_row_base, my_col_base, src_row_base, block_size, num_reqs;
+  int tag = 1;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+
+  extent = smpi_datatype_get_extent(send_type);
+
+  block_size = extent * send_count;
+
+  is_2dmesh(num_procs, &X, &Y);
+  my_row_base = (rank / Y) * Y;
+  my_col_base = rank % Y;
+
+  num_reqs = X;
+  if (Y > X)
+    num_reqs = Y;
+
+  req = (MPI_Request *) xbt_malloc(num_reqs * sizeof(MPI_Request));
+
+  req_ptr = req;
+
+  // do local allgather/local copy 
+  recv_offset = rank * block_size;
+  smpi_datatype_copy(send_buff, send_count, send_type, (char *)recv_buff + recv_offset,
+                 recv_count, recv_type);
+
+  // do row-wise comm
+  for (i = 0; i < Y; i++) {
+    src = i + my_row_base;
+    if (src == rank)
+      continue;
+    recv_offset = src * block_size;
+    *(req_ptr++) = smpi_mpi_irecv((char *)recv_buff + recv_offset, recv_count, recv_type, src, tag,
+               comm);
+  }
+
+
+  for (i = 0; i < Y; i++) {
+    dst = i + my_row_base;
+    if (dst == rank)
+      continue;
+    smpi_mpi_send(send_buff, send_count, send_type, dst, tag, comm);
+  }
+
+  smpi_mpi_waitall(Y - 1, req, MPI_STATUSES_IGNORE);
+
+  req_ptr = req;
+
+  // do colwise comm
+  for (i = 0; i < X; i++) {
+    src = (i * Y + my_col_base);
+    if (src == rank)
+      continue;
+    src_row_base = (src / Y) * Y;
+    recv_offset = src_row_base * block_size;
+    *(req_ptr++) = smpi_mpi_irecv((char *)recv_buff + recv_offset, recv_count * Y, recv_type, src, tag,
+               comm);
+  }
+
+  for (i = 0; i < X; i++) {
+    dst = (i * Y + my_col_base);
+    if (dst == rank)
+      continue;
+    send_offset = my_row_base * block_size;
+    smpi_mpi_send((char *)recv_buff + send_offset, send_count * Y, send_type, dst, tag,
+              comm);
+  }
+
+  smpi_mpi_waitall(X - 1, req, MPI_STATUSES_IGNORE);
+
+  free(req);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-3dmesh.c b/src/smpi/colls/allgather-3dmesh.c
new file mode 100644 (file)
index 0000000..dfd2ace
--- /dev/null
@@ -0,0 +1,200 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+ * Function: is_2dmesh
+ * return: int
+ * num: the number of processors in a communicator
+ * i: x dimension
+ * j: y dimension
+ * k: z dimension
+ * descp: takes a number and tries to find a factoring of x*y*z mesh out of it
+ ****************************************************************************/
+#ifndef THREED
+#define THREED
+static int is_3dmesh(int num, int *i, int *j, int *k)
+{
+  int x, max = num / 3;
+  x = cbrt(num);
+  *i = *j = *k = 0;
+  while (x <= max) {
+    if ((num % (x * x)) == 0) {
+      *i = *j = x;
+      *k = num / (x * x);
+      return 1;
+    }
+    x++;
+  }
+  return 0;
+}
+#endif
+/*****************************************************************************
+ * Function: allgather_3dmesh_shoot
+ * return: int
+ * send_buff: send input buffer
+ * send_count: number of elements to send
+ * send_type: data type of elements being sent
+ * recv_buff: receive output buffer
+ * recv_count: number of elements to received
+ * recv_type: data type of elements being received
+ * comm: communication
+ * Descrp: Function realizes the allgather operation using the 2dmesh
+ * algorithm. Allgather ommunication occurs first in the x dimension, y
+ * dimension, and then in the z dimension. Communication in each dimension
+ * follows "simple"
+ * Auther: Ahmad Faraj
+****************************************************************************/
+int smpi_coll_tuned_allgather_3dmesh(void *send_buff, int send_count,
+                                     MPI_Datatype send_type, void *recv_buff,
+                                     int recv_count, MPI_Datatype recv_type,
+                                     MPI_Comm comm)
+{
+  MPI_Request *req, *req_ptr;
+  MPI_Aint extent;
+
+  int i, src, dst, rank, num_procs, block_size, my_z_base;
+  int my_z, X, Y, Z, send_offset, recv_offset;
+  int two_dsize, my_row_base, my_col_base, src_row_base, src_z_base, num_reqs;
+  int tag = 1;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
+
+  is_3dmesh(num_procs, &X, &Y, &Z);
+
+  num_reqs = X;
+
+  if (Y > X)
+    num_reqs = Y;
+  if (Z > Y)
+    num_reqs = Z;
+
+  two_dsize = X * Y;
+  my_z = rank / two_dsize;
+
+  my_row_base = (rank / X) * X;
+  my_col_base = (rank % Y) + (my_z * two_dsize);
+  my_z_base = my_z * two_dsize;
+
+  block_size = extent * send_count;
+
+  req = (MPI_Request *) xbt_malloc(num_reqs * sizeof(MPI_Request));
+
+  req_ptr = req;
+
+  // do local allgather/local copy 
+  recv_offset = rank * block_size;
+  smpi_datatype_copy(send_buff, send_count, send_type, (char *)recv_buff + recv_offset,
+                 recv_count, recv_type);
+
+  // do rowwise comm 
+  for (i = 0; i < Y; i++) {
+    src = i + my_row_base;
+    if (src == rank)
+      continue;
+    recv_offset = src * block_size;
+    *(req_ptr++) = smpi_mpi_irecv((char *)recv_buff + recv_offset, send_count, recv_type, src, tag,
+               comm);
+  }
+
+  for (i = 0; i < Y; i++) {
+    dst = i + my_row_base;
+    if (dst == rank)
+      continue;
+    smpi_mpi_send(send_buff, send_count, send_type, dst, tag, comm);
+  }
+
+  smpi_mpi_waitall(Y - 1, req, MPI_STATUSES_IGNORE);
+  req_ptr = req;
+
+  // do colwise comm, it does not matter here if i*X or i *Y since X == Y
+
+  for (i = 0; i < X; i++) {
+    src = (i * Y + my_col_base);
+    if (src == rank)
+      continue;
+
+    src_row_base = (src / X) * X;
+    recv_offset = src_row_base * block_size;
+    *(req_ptr++) = smpi_mpi_irecv((char *)recv_buff + recv_offset, recv_count * Y, recv_type, src, tag,
+               comm);
+  }
+
+  send_offset = my_row_base * block_size;
+
+  for (i = 0; i < X; i++) {
+    dst = (i * Y + my_col_base);
+    if (dst == rank)
+      continue;
+    smpi_mpi_send((char *)recv_buff + send_offset, send_count * Y, send_type, dst, tag,
+              comm);
+  }
+
+  smpi_mpi_waitall(X - 1, req, MPI_STATUSES_IGNORE);
+  req_ptr = req;
+
+  for (i = 1; i < Z; i++) {
+    src = (rank + i * two_dsize) % num_procs;
+    src_z_base = (src / two_dsize) * two_dsize;
+
+    recv_offset = (src_z_base * block_size);
+
+    *(req_ptr++) = smpi_mpi_irecv((char *)recv_buff + recv_offset, recv_count * two_dsize, recv_type,
+               src, tag, comm);
+  }
+
+  for (i = 1; i < Z; i++) {
+    dst = (rank + i * two_dsize) % num_procs;
+    send_offset = my_z_base * block_size;
+    smpi_mpi_send((char *)recv_buff + send_offset, send_count * two_dsize, send_type,
+              dst, tag, comm);
+  }
+  smpi_mpi_waitall(Z - 1, req, MPI_STATUSES_IGNORE);
+
+  free(req);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-GB.c b/src/smpi/colls/allgather-GB.c
new file mode 100644 (file)
index 0000000..f9a1e07
--- /dev/null
@@ -0,0 +1,16 @@
+#include "colls_private.h"
+
+// Allgather - gather/bcast algorithm
+int smpi_coll_tuned_allgather_GB(void *send_buff, int send_count,
+                                 MPI_Datatype send_type, void *recv_buff,
+                                 int recv_count, MPI_Datatype recv_type,
+                                 MPI_Comm comm)
+{
+  int num_procs;
+  num_procs = smpi_comm_size(comm);
+  smpi_mpi_gather(send_buff, send_count, send_type, recv_buff, recv_count, recv_type,
+             0, comm);
+  mpi_coll_bcast_fun(recv_buff, (recv_count * num_procs), recv_type, 0, comm);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-NTSLR-NB.c b/src/smpi/colls/allgather-NTSLR-NB.c
new file mode 100644 (file)
index 0000000..d0c6ef0
--- /dev/null
@@ -0,0 +1,63 @@
+#include "colls_private.h"
+
+// Allgather-Non-Topoloty-Scecific-Logical-Ring algorithm
+int
+smpi_coll_tuned_allgather_NTSLR_NB(void *sbuf, int scount, MPI_Datatype stype,
+                                   void *rbuf, int rcount, MPI_Datatype rtype,
+                                   MPI_Comm comm)
+{
+  MPI_Aint rextent, sextent;
+  MPI_Status status, status2;
+  int i, to, from, rank, size;
+  int send_offset, recv_offset;
+  int tag = 500;
+
+  rank = smpi_comm_rank(comm);
+  size = smpi_comm_size(comm);
+  rextent = smpi_datatype_get_extent(rtype);
+  sextent = smpi_datatype_get_extent(stype);
+  MPI_Request *rrequest_array;
+  MPI_Request *srequest_array;
+  rrequest_array = (MPI_Request *) xbt_malloc(size * sizeof(MPI_Request));
+  srequest_array = (MPI_Request *) xbt_malloc(size * sizeof(MPI_Request));
+
+  // irregular case use default MPI fucntions
+  if (scount * sextent != rcount * rextent) {
+    XBT_WARN("MPI_allgather_NTSLR_NB use default MPI_allgather.");  
+    smpi_mpi_allgather(sbuf, scount, stype, rbuf, rcount, rtype, comm);
+    return MPI_SUCCESS;    
+  }
+
+  // topo non-specific
+  to = (rank + 1) % size;
+  from = (rank + size - 1) % size;
+
+  //copy a single segment from sbuf to rbuf
+  send_offset = rank * scount * sextent;
+
+  smpi_mpi_sendrecv(sbuf, scount, stype, rank, tag,
+               (char *)rbuf + send_offset, rcount, rtype, rank, tag, comm, &status);
+
+
+  //start sending logical ring message
+  int increment = scount * sextent;
+
+  //post all irecv first
+  for (i = 0; i < size - 1; i++) {
+    recv_offset = ((rank - i - 1 + size) % size) * increment;
+    rrequest_array[i] = smpi_mpi_irecv((char *)rbuf + recv_offset, rcount, rtype, from, tag + i, comm);
+  }
+
+
+  for (i = 0; i < size - 1; i++) {
+    send_offset = ((rank - i + size) % size) * increment;
+    srequest_array[i] = smpi_mpi_isend((char *)rbuf + send_offset, scount, stype, to, tag + i, comm);
+    smpi_mpi_wait(&rrequest_array[i], &status);
+    smpi_mpi_wait(&srequest_array[i], &status2);
+  }
+
+  free(rrequest_array);
+  free(srequest_array);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-NTSLR.c b/src/smpi/colls/allgather-NTSLR.c
new file mode 100644 (file)
index 0000000..bcaabfd
--- /dev/null
@@ -0,0 +1,50 @@
+#include "colls_private.h"
+
+// Allgather-Non-Topoloty-Scecific-Logical-Ring algorithm
+int
+smpi_coll_tuned_allgather_NTSLR(void *sbuf, int scount, MPI_Datatype stype,
+                                void *rbuf, int rcount, MPI_Datatype rtype,
+                                MPI_Comm comm)
+{
+  MPI_Aint rextent, sextent;
+  MPI_Status status;
+  int i, to, from, rank, size;
+  int send_offset, recv_offset;
+  int tag = 500;
+
+  rank = smpi_comm_rank(comm);
+  size = smpi_comm_size(comm);
+  rextent = smpi_datatype_get_extent(rtype);
+  sextent = smpi_datatype_get_extent(stype);
+
+  // irregular case use default MPI fucntions
+  if (scount * sextent != rcount * rextent) {
+    XBT_WARN("MPI_allgather_NTSLR use default MPI_allgather.");  
+    smpi_mpi_allgather(sbuf, scount, stype, rbuf, rcount, rtype, comm);
+    return MPI_SUCCESS;    
+  }
+
+  // topo non-specific
+  to = (rank + 1) % size;
+  from = (rank + size - 1) % size;
+
+  //copy a single segment from sbuf to rbuf
+  send_offset = rank * scount * sextent;
+
+  smpi_mpi_sendrecv(sbuf, scount, stype, rank, tag,
+               (char *)rbuf + send_offset, rcount, rtype, rank, tag,
+               comm, &status);
+
+
+  //start sending logical ring message
+  int increment = scount * sextent;
+  for (i = 0; i < size - 1; i++) {
+    send_offset = ((rank - i + size) % size) * increment;
+    recv_offset = ((rank - i - 1 + size) % size) * increment;
+    smpi_mpi_sendrecv((char *) rbuf + send_offset, scount, stype, to, tag + i,
+                 (char *) rbuf + recv_offset, rcount, rtype, from, tag + i,
+                 comm, &status);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-SMP-NTS.c b/src/smpi/colls/allgather-SMP-NTS.c
new file mode 100644 (file)
index 0000000..a6b515a
--- /dev/null
@@ -0,0 +1,140 @@
+#include "colls_private.h"
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+int smpi_coll_tuned_allgather_SMP_NTS(void *sbuf, int scount,
+                                      MPI_Datatype stype, void *rbuf,
+                                      int rcount, MPI_Datatype rtype,
+                                      MPI_Comm comm)
+{
+  int src, dst, comm_size, rank;
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint rextent, sextent;
+  rextent = smpi_datatype_get_extent(rtype);
+  sextent = smpi_datatype_get_extent(stype);
+  int tag = 50;
+  MPI_Request request;
+  MPI_Request rrequest_array[128];
+
+  MPI_Status status;
+  int i, send_offset, recv_offset;
+  int intra_rank, inter_rank;
+  intra_rank = rank % NUM_CORE;
+  inter_rank = rank / NUM_CORE;
+  int inter_comm_size = (comm_size + NUM_CORE - 1) / NUM_CORE;
+  int num_core_in_current_smp = NUM_CORE;
+
+  /* for too small number of processes, use default implementation */
+  if (comm_size <= NUM_CORE) {
+    XBT_WARN("MPI_allgather_SMP_NTS use default MPI_allgather.");        
+    smpi_mpi_allgather(sbuf, scount, stype, rbuf, rcount, rtype, comm);
+    return MPI_SUCCESS;    
+  }
+
+  // the last SMP node may have fewer number of running processes than all others
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * NUM_CORE);
+  }
+  //copy corresponding message from sbuf to rbuf
+  recv_offset = rank * rextent * rcount;
+  smpi_mpi_sendrecv(sbuf, scount, stype, rank, tag,
+               ((char *) rbuf + recv_offset), rcount, rtype, rank, tag, comm,
+               &status);
+
+  //gather to root of each SMP
+
+  for (i = 1; i < num_core_in_current_smp; i++) {
+
+    dst =
+        (inter_rank * NUM_CORE) + (intra_rank + i) % (num_core_in_current_smp);
+    src =
+        (inter_rank * NUM_CORE) + (intra_rank - i +
+                                   num_core_in_current_smp) %
+        (num_core_in_current_smp);
+    recv_offset = src * rextent * rcount;
+
+    smpi_mpi_sendrecv(sbuf, scount, stype, dst, tag,
+                 ((char *) rbuf + recv_offset), rcount, rtype, src, tag, comm,
+                 &status);
+
+  }
+
+  // INTER-SMP-ALLGATHER 
+  // Every root of each SMP node post INTER-Sendrecv, then do INTRA-Bcast for each receiving message
+  // Use logical ring algorithm
+
+  // root of each SMP
+  if (intra_rank == 0) {
+    src = ((inter_rank - 1 + inter_comm_size) % inter_comm_size) * NUM_CORE;
+    dst = ((inter_rank + 1) % inter_comm_size) * NUM_CORE;
+
+    // post all inter Irecv
+    for (i = 0; i < inter_comm_size - 1; i++) {
+      recv_offset =
+          ((inter_rank - i - 1 +
+            inter_comm_size) % inter_comm_size) * NUM_CORE * sextent * scount;
+      rrequest_array[i] = smpi_mpi_irecv((char *)rbuf+recv_offset, rcount * NUM_CORE, rtype, src, tag+i, comm);
+    }
+
+    // send first message
+    send_offset =
+        ((inter_rank +
+          inter_comm_size) % inter_comm_size) * NUM_CORE * sextent * scount;
+    smpi_mpi_isend((char *) rbuf + send_offset, scount * NUM_CORE, stype,
+                   dst, tag, comm);
+
+    // loop : recv-inter , send-inter, send-intra (linear-bcast)
+    for (i = 0; i < inter_comm_size - 2; i++) {
+      recv_offset =
+          ((inter_rank - i - 1 +
+            inter_comm_size) % inter_comm_size) * NUM_CORE * sextent * scount;
+      smpi_mpi_wait(&rrequest_array[i], &status);
+      smpi_mpi_isend((char *) rbuf + recv_offset, scount * NUM_CORE, stype,
+                     dst, tag + i + 1, comm);
+      if (num_core_in_current_smp > 1) {
+        request = smpi_mpi_isend((char *) rbuf + recv_offset, scount * NUM_CORE, stype,
+                  (rank + 1), tag + i + 1, comm);
+      }
+    }
+
+    // recv last message and send_intra
+    recv_offset =
+        ((inter_rank - i - 1 +
+          inter_comm_size) % inter_comm_size) * NUM_CORE * sextent * scount;
+    //recv_offset = ((inter_rank + 1) % inter_comm_size) * NUM_CORE * sextent * scount;
+    //i=inter_comm_size-2;
+    smpi_mpi_wait(&rrequest_array[i], &status);
+    if (num_core_in_current_smp > 1) {
+      request = smpi_mpi_isend((char *) rbuf + recv_offset, scount * NUM_CORE, stype,
+                (rank + 1), tag + i + 1, comm);
+    }
+  }
+  // last rank of each SMP
+  else if (intra_rank == (num_core_in_current_smp - 1)) {
+    for (i = 0; i < inter_comm_size - 1; i++) {
+      recv_offset =
+          ((inter_rank - i - 1 +
+            inter_comm_size) % inter_comm_size) * NUM_CORE * sextent * scount;
+      request = smpi_mpi_irecv((char *) rbuf + recv_offset, (rcount * NUM_CORE), rtype,
+                rank - 1, tag + i + 1, comm);
+      smpi_mpi_wait(&request, &status);
+    }
+  }
+  // intermediate rank of each SMP
+  else {
+    for (i = 0; i < inter_comm_size - 1; i++) {
+      recv_offset =
+          ((inter_rank - i - 1 +
+            inter_comm_size) % inter_comm_size) * NUM_CORE * sextent * scount;
+      request = smpi_mpi_irecv((char *) rbuf + recv_offset, (rcount * NUM_CORE), rtype,
+                rank - 1, tag + i + 1, comm);
+      smpi_mpi_wait(&request, &status);
+      request = smpi_mpi_isend((char *) rbuf + recv_offset, (scount * NUM_CORE), stype,
+                (rank + 1), tag + i + 1, comm);
+    }
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-bruck.c b/src/smpi/colls/allgather-bruck.c
new file mode 100644 (file)
index 0000000..681690a
--- /dev/null
@@ -0,0 +1,129 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+
+/*****************************************************************************
+ * Function: allgather_bruck
+ * return: int
+ * inputs:
+ *   send_buff: send input buffer
+ *   send_count: number of elements to send
+ *   send_type: data type of elements being sent
+ *   recv_buff: receive output buffer
+ *   recv_count: number of elements to received
+ *   recv_type: data type of elements being received
+ *   comm: communication
+ * Descrp: Function realizes the allgather operation using the bruck
+ *         algorithm.
+ * Auther: MPICH
+ * Comment: Original bruck algorithm from MPICH is slightly modified by
+ *          Ahmad Faraj.  
+ ****************************************************************************/
+int smpi_coll_tuned_allgather_bruck(void *send_buff, int send_count,
+                                    MPI_Datatype send_type, void *recv_buff,
+                                    int recv_count, MPI_Datatype recv_type,
+                                    MPI_Comm comm)
+{
+  // MPI variables
+  MPI_Status status;
+  MPI_Aint recv_extent;
+
+  // local int variables
+  int src, dst, rank, num_procs, count, remainder;
+  int tag = 1;
+  int pof2 = 1;
+
+  // local string variables
+  char *tmp_buff;
+  char *send_ptr = (char *) send_buff;
+  char *recv_ptr = (char *) recv_buff;
+
+  // get size of the communicator, followed by rank 
+  num_procs = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+
+  // get size of single element's type for recv buffer
+  recv_extent = smpi_datatype_get_extent(recv_type);
+
+  count = recv_count;
+
+  tmp_buff = (char *) xbt_malloc(num_procs * recv_count * recv_extent);
+
+  // perform a local copy
+  smpi_datatype_copy(send_ptr, send_count, send_type,
+                    tmp_buff, recv_count, recv_type);
+  while (pof2 <= (num_procs / 2)) {
+    src = (rank + pof2) % num_procs;
+    dst = (rank - pof2 + num_procs) % num_procs;
+
+    smpi_mpi_sendrecv(tmp_buff, count, recv_type, dst, tag,
+                  tmp_buff + count * recv_extent, count, recv_type,
+                  src, tag, comm, &status);
+    count *= 2;
+    pof2 *= 2;
+  }
+
+  remainder = num_procs - pof2;
+  if (remainder) {
+    src = (rank + pof2) % num_procs;
+    dst = (rank - pof2 + num_procs) % num_procs;
+
+    smpi_mpi_sendrecv(tmp_buff, remainder * recv_count, recv_type, dst, tag,
+                  tmp_buff + count * recv_extent, remainder * recv_count,
+                  recv_type, src, tag, comm, &status);
+  }
+
+  smpi_mpi_sendrecv(tmp_buff, (num_procs - rank) * recv_count, recv_type, rank,
+                tag, recv_ptr + rank * recv_count * recv_extent,
+                (num_procs - rank) * recv_count, recv_type, rank, tag, comm,
+                &status);
+
+  if (rank)
+    smpi_mpi_sendrecv(tmp_buff + (num_procs - rank) * recv_count * recv_extent,
+                  rank * recv_count, recv_type, rank, tag, recv_ptr,
+                  rank * recv_count, recv_type, rank, tag, comm, &status);
+  free(tmp_buff);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-loosely-lr.c b/src/smpi/colls/allgather-loosely-lr.c
new file mode 100644 (file)
index 0000000..6455db1
--- /dev/null
@@ -0,0 +1,119 @@
+#include "colls_private.h"
+
+#ifndef NUM_CORE
+#define NUM_CORE 4
+#endif
+
+int smpi_coll_tuned_allgather_loosely_lr(void *sbuf, int scount,
+                                         MPI_Datatype stype, void *rbuf,
+                                         int rcount, MPI_Datatype rtype,
+                                         MPI_Comm comm)
+{
+  int comm_size, rank;
+  int tag = 50;
+  int i, j, send_offset, recv_offset;
+  int intra_rank, inter_rank, inter_comm_size, intra_comm_size;
+  int inter_dst, inter_src;
+
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint rextent, sextent;
+  rextent = smpi_datatype_get_extent(rtype);
+  sextent = smpi_datatype_get_extent(stype);
+  MPI_Request inter_rrequest;
+  MPI_Request rrequest_array[128];
+  MPI_Request srequest_array[128];
+  MPI_Request inter_srequest_array[128];
+
+
+  int rrequest_count = 0;
+  int srequest_count = 0;
+  int inter_srequest_count = 0;
+
+  MPI_Status status;
+
+  intra_rank = rank % NUM_CORE;
+  inter_rank = rank / NUM_CORE;
+  inter_comm_size = (comm_size + NUM_CORE - 1) / NUM_CORE;
+  intra_comm_size = NUM_CORE;
+
+  int src_seg, dst_seg;
+
+  //copy corresponding message from sbuf to rbuf
+  recv_offset = rank * rextent * rcount;
+  smpi_mpi_sendrecv(sbuf, scount, stype, rank, tag,
+               (char *)rbuf + recv_offset, rcount, rtype, rank, tag, comm, &status);
+
+  int dst, src;
+  int inter_send_offset, inter_recv_offset;
+
+  rrequest_count = 0;
+  srequest_count = 0;
+  inter_srequest_count = 0;
+
+  for (i = 0; i < inter_comm_size; i++) {
+
+    // inter_communication
+
+    inter_dst = (rank + intra_comm_size) % comm_size;
+    inter_src = (rank - intra_comm_size + comm_size) % comm_size;
+
+    src_seg =
+        ((inter_rank - 1 - i +
+          inter_comm_size) % inter_comm_size) * intra_comm_size + intra_rank;
+    dst_seg =
+        ((inter_rank - i +
+          inter_comm_size) % inter_comm_size) * intra_comm_size + intra_rank;
+
+    inter_send_offset = dst_seg * sextent * scount;
+    inter_recv_offset = src_seg * rextent * rcount;
+
+    for (j = 0; j < intra_comm_size; j++) {
+
+      // inter communication
+      if (intra_rank == j) {
+        if (i != inter_comm_size - 1) {
+
+          inter_rrequest = smpi_mpi_irecv((char *)rbuf + inter_recv_offset, rcount, rtype,
+                                         inter_src, tag, comm);
+          inter_srequest_array[inter_srequest_count++] = smpi_mpi_isend((char *)rbuf + inter_send_offset, scount, stype,
+                                                                       inter_dst, tag, comm);
+        }
+      }
+      //intra_communication
+      src = inter_rank * intra_comm_size + j;
+      dst = inter_rank * intra_comm_size + j;
+
+      src_seg =
+          ((inter_rank - i +
+            inter_comm_size) % inter_comm_size) * intra_comm_size + j;
+      dst_seg =
+          ((inter_rank - i +
+            inter_comm_size) % inter_comm_size) * intra_comm_size + intra_rank;
+
+      send_offset = dst_seg * sextent * scount;
+      recv_offset = src_seg * rextent * rcount;
+
+
+      if (j != intra_rank) {
+
+        rrequest_array[rrequest_count++] = smpi_mpi_irecv((char *)rbuf + recv_offset, rcount, rtype, src, tag, comm);
+        srequest_array[srequest_count++] = smpi_mpi_isend((char *)rbuf + send_offset, scount, stype, dst, tag, comm);
+
+      }
+    }                           // intra loop
+
+
+    // wait for inter communication to finish for these rounds (# of round equals NUM_CORE)
+    if (i != inter_comm_size - 1) {
+      smpi_mpi_wait(&inter_rrequest, &status);
+    }
+
+  }                             //inter loop
+
+  smpi_mpi_waitall(rrequest_count, rrequest_array, MPI_STATUSES_IGNORE);
+  smpi_mpi_waitall(srequest_count, srequest_array, MPI_STATUSES_IGNORE);
+  smpi_mpi_waitall(inter_srequest_count, inter_srequest_array, MPI_STATUSES_IGNORE);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-lr.c b/src/smpi/colls/allgather-lr.c
new file mode 100644 (file)
index 0000000..7656069
--- /dev/null
@@ -0,0 +1,48 @@
+#include "colls_private.h"
+
+// Allgather-Non-Topoloty-Scecific-Logical-Ring algorithm
+int
+smpi_coll_tuned_allgather_lr(void *sbuf, int scount, MPI_Datatype stype,
+                             void *rbuf, int rcount, MPI_Datatype rtype,
+                             MPI_Comm comm)
+{
+  MPI_Aint rextent, sextent;
+  MPI_Status status;
+  int i, to, from, rank, size;
+  int send_offset, recv_offset;
+  int tag = 500;
+
+  rank = smpi_comm_rank(comm);
+  size = smpi_comm_size(comm);
+  rextent = smpi_datatype_get_extent(rtype);
+  sextent = smpi_datatype_get_extent(stype);
+
+  // irregular case use default MPI fucntions
+  if (scount * sextent != rcount * rextent) {
+    XBT_WARN("MPI_allgather_lr use default MPI_allgather.");     
+    smpi_mpi_allgather(sbuf, scount, stype, rbuf, rcount, rtype, comm);
+    return MPI_SUCCESS;
+  }
+
+  // topo non-specific
+  to = (rank + 1) % size;
+  from = (rank + size - 1) % size;
+
+  //copy a single segment from sbuf to rbuf
+  send_offset = rank * scount * sextent;
+  smpi_mpi_sendrecv(sbuf, scount, stype, rank, tag,
+               (char *) rbuf + send_offset, rcount, rtype, rank, tag,
+               comm, &status);
+
+  //start sending logical ring message
+  int increment = scount * sextent;
+  for (i = 0; i < size - 1; i++) {
+    send_offset = ((rank - i + size) % size) * increment;
+    recv_offset = ((rank - i - 1 + size) % size) * increment;
+    smpi_mpi_sendrecv((char *) rbuf + send_offset, scount, stype, to, tag + i,
+                 (char *) rbuf + recv_offset, rcount, rtype, from, tag + i,
+                 comm, &status);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-pair.c b/src/smpi/colls/allgather-pair.c
new file mode 100644 (file)
index 0000000..0dc4aec
--- /dev/null
@@ -0,0 +1,93 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+ * Function: allgather_pair
+ * return: int
+ *  inputs:
+ *   send_buff: send input buffer
+ *   send_count: number of elements to send
+ *   send_type: data type of elements being sent
+ *   recv_buff: receive output buffer
+ *   recv_count: number of elements to received
+ *   recv_type: data type of elements being received
+ *   comm: communication
+ * Descrp: Function works when P is power of two. In each phase of P - 1
+ *         phases, nodes in pair communicate their data.
+ * Auther: Ahmad Faraj
+ ****************************************************************************/
+int
+smpi_coll_tuned_allgather_pair(void *send_buff, int send_count,
+                               MPI_Datatype send_type, void *recv_buff,
+                               int recv_count, MPI_Datatype recv_type,
+                               MPI_Comm comm)
+{
+
+  MPI_Aint extent;
+  int i, src, dst, rank, num_procs;
+  int tag = 1;
+  MPI_Status status;
+
+  char *send_ptr = (char *) send_buff;
+  char *recv_ptr = (char *) recv_buff;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
+
+  // local send/recv
+  smpi_mpi_sendrecv(send_ptr, send_count, send_type, rank, tag,
+               recv_ptr + rank * recv_count * extent,
+               recv_count, recv_type, rank, tag, comm, &status);
+
+  for (i = 1; i < num_procs; i++) {
+    src = dst = rank ^ i;
+    smpi_mpi_sendrecv(send_ptr, send_count, send_type, dst, tag,
+                 recv_ptr + src * recv_count * extent, recv_count, recv_type,
+                 src, tag, comm, &status);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-rdb.c b/src/smpi/colls/allgather-rdb.c
new file mode 100644 (file)
index 0000000..520819a
--- /dev/null
@@ -0,0 +1,123 @@
+#include "colls_private.h"
+
+int
+smpi_coll_tuned_allgather_rdb(void *sbuf, int send_count,
+                              MPI_Datatype send_type, void *rbuf,
+                              int recv_count, MPI_Datatype recv_type,
+                              MPI_Comm comm)
+{
+  // MPI variables
+  MPI_Status status;
+  MPI_Aint send_chunk, recv_chunk;
+
+  // local int variables
+  int i, j, k, dst, rank, num_procs, send_offset, recv_offset, tree_root;
+  int dst_tree_root, rank_tree_root, last_recv_count = 0, num_procs_completed;
+  int offset, tmp_mask;
+  int tag = 1;
+  int mask = 1;
+  int success = 0;
+  int curr_count = recv_count;
+
+  // local string variables
+  char *send_ptr = (char *) sbuf;
+  char *recv_ptr = (char *) rbuf;
+
+  // get size of the communicator, followed by rank 
+  num_procs = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+
+  // get size of single element's type for send buffer and recv buffer
+  send_chunk = smpi_datatype_get_extent(send_type);
+  recv_chunk = smpi_datatype_get_extent(recv_type);
+
+  // multiply size of each element by number of elements to send or recv
+  send_chunk *= send_count;
+  recv_chunk *= recv_count;
+
+  // perform a local copy
+  smpi_mpi_sendrecv(send_ptr, send_count, send_type, rank, tag,
+               recv_ptr + rank * recv_chunk, recv_count, recv_type, rank, tag,
+               comm, &status);
+
+  i = 0;
+  while (mask < num_procs) {
+    dst = rank ^ mask;
+    dst_tree_root = dst >> i;
+    dst_tree_root <<= i;
+    rank_tree_root = rank >> i;
+    rank_tree_root <<= i;
+    send_offset = rank_tree_root * send_chunk;
+    recv_offset = dst_tree_root * recv_chunk;
+
+    if (dst < num_procs) {
+      smpi_mpi_sendrecv(recv_ptr + send_offset, curr_count, send_type, dst,
+                   tag, recv_ptr + recv_offset, mask * recv_count,
+                   recv_type, dst, tag, comm, &status);
+      last_recv_count = smpi_mpi_get_count(&status, recv_type);
+      curr_count += last_recv_count;
+    }
+
+    if (dst_tree_root + mask > num_procs) {
+      num_procs_completed = num_procs - rank_tree_root - mask;
+      /* num_procs_completed is the number of processes in this
+         subtree that have all the data. Send data to others
+         in a tree fashion. First find root of current tree
+         that is being divided into two. k is the number of
+         least-significant bits in this process's rank that
+         must be zeroed out to find the rank of the root */
+
+      j = mask;
+      k = 0;
+      while (j) {
+        j >>= 1;
+        k++;
+      }
+      k--;
+
+      offset = recv_chunk * (rank_tree_root + mask);
+      tmp_mask = mask >> 1;
+
+      while (tmp_mask) {
+        dst = rank ^ tmp_mask;
+
+        tree_root = rank >> k;
+        tree_root <<= k;
+
+        /* send only if this proc has data and destination
+           doesn't have data. at any step, multiple processes
+           can send if they have the data */
+        if ((dst > rank)
+            && (rank < tree_root + num_procs_completed)
+            && (dst >= tree_root + num_procs_completed)) {
+          smpi_mpi_send(recv_ptr + offset, last_recv_count, recv_type, dst,
+                   tag, comm);
+
+          /* last_recv_cnt was set in the previous
+             receive. that's the amount of data to be
+             sent now. */
+        }
+        /* recv only if this proc. doesn't have data and sender
+           has data */
+        else if ((dst < rank)
+                 && (dst < tree_root + num_procs_completed)
+                 && (rank >= tree_root + num_procs_completed)) {
+          smpi_mpi_recv(recv_ptr + offset,
+                   recv_count * num_procs_completed,
+                   recv_type, dst, tag, comm, &status);
+          // num_procs_completed is also equal to the no. of processes
+          // whose data we don't have
+          last_recv_count = smpi_mpi_get_count(&status, recv_type);
+          curr_count += last_recv_count;
+        }
+        tmp_mask >>= 1;
+        k--;
+      }
+    }
+
+    mask <<= 1;
+    i++;
+  }
+
+  return success;
+}
diff --git a/src/smpi/colls/allgather-rhv.c b/src/smpi/colls/allgather-rhv.c
new file mode 100644 (file)
index 0000000..c3db821
--- /dev/null
@@ -0,0 +1,96 @@
+#include "colls_private.h"
+
+// now only work with power of two processes
+
+int
+smpi_coll_tuned_allgather_rhv(void *sbuf, int send_count,
+                              MPI_Datatype send_type, void *rbuf,
+                              int recv_count, MPI_Datatype recv_type,
+                              MPI_Comm comm)
+{
+  MPI_Status status;
+  MPI_Aint s_extent, r_extent;
+
+  // local int variables
+  int i, dst, send_base_offset, recv_base_offset, send_chunk, recv_chunk,
+      send_offset, recv_offset;
+  int rank, num_procs;
+  int tag = 50;
+  int mask;
+  int curr_count;
+
+  // get size of the communicator, followed by rank 
+  num_procs = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+
+  // get size of single element's type for send buffer and recv buffer
+  s_extent = smpi_datatype_get_extent(send_type);
+  r_extent = smpi_datatype_get_extent(recv_type);
+
+  // multiply size of each element by number of elements to send or recv
+  send_chunk = s_extent * send_count;
+  recv_chunk = r_extent * recv_count;
+
+  if (send_chunk != recv_chunk) {
+    XBT_WARN("MPI_allgather_rhv use default MPI_allgather.");  
+    smpi_mpi_allgather(sbuf, send_count, send_type, rbuf, recv_count,
+                              recv_type, comm);
+    return MPI_SUCCESS;        
+  }
+
+  // compute starting offset location to perform local copy
+  int size = num_procs / 2;
+  int base_offset = 0;
+  mask = 1;
+  while (mask < num_procs) {
+    if (rank & mask) {
+      base_offset += size;
+    }
+    mask <<= 1;
+    size /= 2;
+  }
+
+  //  printf("node %d base_offset %d\n",rank,base_offset);
+
+  //perform a remote copy
+
+  dst = base_offset;
+  smpi_mpi_sendrecv(sbuf, send_count, send_type, dst, tag,
+               (char *)rbuf + base_offset * recv_chunk, recv_count, recv_type, dst, tag,
+               comm, &status);
+
+
+  mask >>= 1;
+  i = 1;
+  int phase = 0;
+  curr_count = recv_count;
+  while (mask >= 1) {
+    // destination pair for both send and recv
+    dst = rank ^ mask;
+
+    // compute offsets
+    send_base_offset = base_offset;
+    if (rank & mask) {
+      recv_base_offset = base_offset - i;
+      base_offset -= i;
+    } else {
+      recv_base_offset = base_offset + i;
+    }
+    send_offset = send_base_offset * recv_chunk;
+    recv_offset = recv_base_offset * recv_chunk;
+
+    //  printf("node %d send to %d in phase %d s_offset = %d r_offset = %d count = %d\n",rank,dst,phase, send_base_offset, recv_base_offset, curr_count);
+
+    smpi_mpi_sendrecv((char *)rbuf + send_offset, curr_count, recv_type, dst, tag,
+                (char *)rbuf + recv_offset, curr_count, recv_type, dst, tag,
+                 comm, &status);
+
+
+    curr_count *= 2;
+    i *= 2;
+    mask >>= 1;
+    phase++;
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-ring.c b/src/smpi/colls/allgather-ring.c
new file mode 100644 (file)
index 0000000..6108ae5
--- /dev/null
@@ -0,0 +1,93 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+ * Function: allgather_ring
+ * return: int
+ * inputs:
+ *   send_buff: send input buffer
+ *   send_count: number of elements to send
+ *   send_type: data type of elements being sent
+ *   recv_buff: receive output buffer
+ *   recv_count: number of elements to received
+ *   recv_type: data type of elements being received
+ *   comm: communication
+ * Descrp: Function works in P - 1 steps. In step i, node j - i -> j -> j+ i.
+ * Auther: Ahmad Faraj
+ ****************************************************************************/
+int
+smpi_coll_tuned_allgather_ring(void *send_buff, int send_count,
+                               MPI_Datatype send_type, void *recv_buff,
+                               int recv_count, MPI_Datatype recv_type,
+                               MPI_Comm comm)
+{
+
+  MPI_Aint extent;
+  int i, src, dst, rank, num_procs;
+  int tag = 1;
+  MPI_Status status;
+
+  char *sendptr = (char *) send_buff;
+  char *recvptr = (char *) recv_buff;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
+
+  // local send/recv
+  smpi_mpi_sendrecv(sendptr, send_count, send_type, rank, tag,
+               recvptr + rank * recv_count * extent,
+               recv_count, recv_type, rank, tag, comm, &status);
+
+  for (i = 1; i < num_procs; i++) {
+    src = (rank - i + num_procs) % num_procs;
+    dst = (rank + i) % num_procs;
+    smpi_mpi_sendrecv(sendptr, send_count, send_type, dst, tag,
+                 recvptr + src * recv_count * extent, recv_count, recv_type,
+                 src, tag, comm, &status);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-smp-simple.c b/src/smpi/colls/allgather-smp-simple.c
new file mode 100644 (file)
index 0000000..21cab26
--- /dev/null
@@ -0,0 +1,109 @@
+#include "colls_private.h"
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+int smpi_coll_tuned_allgather_smp_simple(void *send_buf, int scount,
+                                         MPI_Datatype stype, void *recv_buf,
+                                         int rcount, MPI_Datatype rtype,
+                                         MPI_Comm comm)
+{
+  int src, dst, comm_size, rank;
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint rextent, sextent;
+  rextent = smpi_datatype_get_extent(rtype);
+  sextent = smpi_datatype_get_extent(stype);
+  int tag = 50;
+  MPI_Status status;
+  int i, send_offset, recv_offset;
+  int intra_rank, inter_rank;
+  int num_core = NUM_CORE;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+  int num_core_in_current_smp = num_core;
+
+  // the last SMP node may have fewer number of running processes than all others
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * num_core);
+  }
+  //INTRA-SMP-ALLGATHER
+  recv_offset = rank * rextent * rcount;
+  smpi_mpi_sendrecv(send_buf, scount, stype, rank, tag,
+               ((char *) recv_buf + recv_offset), rcount, rtype, rank, tag,
+               comm, &status);
+  for (i = 1; i < num_core_in_current_smp; i++) {
+
+    dst =
+        (inter_rank * num_core) + (intra_rank + i) % (num_core_in_current_smp);
+    src =
+        (inter_rank * num_core) + (intra_rank - i +
+                                   num_core_in_current_smp) %
+        (num_core_in_current_smp);
+    recv_offset = src * rextent * rcount;
+
+    smpi_mpi_sendrecv(send_buf, scount, stype, dst, tag,
+                 ((char *) recv_buf + recv_offset), rcount, rtype, src, tag,
+                 comm, &status);
+
+  }
+
+  // INTER-SMP-ALLGATHER 
+  // Every root of each SMP node post INTER-Sendrecv, then do INTRA-Bcast for each receiving message
+
+
+
+  if (intra_rank == 0) {
+    MPI_Request *reqs, *req_ptr;
+    int num_req = (inter_comm_size - 1) * 2;
+    reqs = (MPI_Request *) xbt_malloc(num_req * sizeof(MPI_Request));
+    req_ptr = reqs;
+    MPI_Status *stat;
+    stat = (MPI_Status *) xbt_malloc(num_req * sizeof(MPI_Status));
+
+    for (i = 1; i < inter_comm_size; i++) {
+
+      //dst = ((inter_rank+i)%inter_comm_size) * num_core;
+      src = ((inter_rank - i + inter_comm_size) % inter_comm_size) * num_core;
+      //send_offset = (rank * sextent * scount);
+      recv_offset = (src * sextent * scount);
+      //      smpi_mpi_sendrecv((recv_buf+send_offset), (scount * num_core), stype, dst, tag, 
+      //             (recv_buf+recv_offset), (rcount * num_core), rtype, src, tag, comm, &status);
+      //MPIC_Isend((recv_buf+send_offset), (scount * num_core), stype, dst, tag, comm, req_ptr++);
+      *(req_ptr++) = smpi_mpi_irecv(((char *) recv_buf + recv_offset), (rcount * num_core), rtype,
+                src, tag, comm);
+    }
+    for (i = 1; i < inter_comm_size; i++) {
+
+      dst = ((inter_rank + i) % inter_comm_size) * num_core;
+      //src = ((inter_rank-i+inter_comm_size)%inter_comm_size) * num_core;
+      send_offset = (rank * sextent * scount);
+      //recv_offset = (src * sextent * scount);
+      //      smpi_mpi_sendrecv((recv_buf+send_offset), (scount * num_core), stype, dst, tag, 
+      //             (recv_buf+recv_offset), (rcount * num_core), rtype, src, tag, comm, &status);
+      *(req_ptr++) = smpi_mpi_isend(((char *) recv_buf + send_offset), (scount * num_core), stype,
+                dst, tag, comm);
+      //MPIC_Irecv((recv_buf+recv_offset), (rcount * num_core), rtype, src, tag, comm, req_ptr++);
+    }
+    smpi_mpi_waitall(num_req, reqs, stat);
+    free(reqs);
+    free(stat);
+
+  }
+  //INTRA-BCAST (use flat tree)
+
+  if (intra_rank == 0) {
+    for (i = 1; i < num_core_in_current_smp; i++) {
+      //printf("rank = %d, num = %d send to %d\n",rank, num_core_in_current_smp, (rank + i));
+      smpi_mpi_send(recv_buf, (scount * comm_size), stype, (rank + i), tag, comm);
+    }
+  } else {
+    //printf("rank = %d recv from %d\n",rank, (inter_rank * num_core));
+    smpi_mpi_recv(recv_buf, (rcount * comm_size), rtype, (inter_rank * num_core),
+             tag, comm, &status);
+  }
+
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgather-spreading-simple.c b/src/smpi/colls/allgather-spreading-simple.c
new file mode 100644 (file)
index 0000000..822ab53
--- /dev/null
@@ -0,0 +1,113 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+ * Function: allgather_spreading_simple
+ * return: int
+ *  inputs:
+ *   send_buff: send input buffer
+ *   send_count: number of elements to send
+ *   send_type: data type of elements being sent
+ *   recv_buff: receive output buffer
+ *   recv_count: number of elements to received
+ *   recv_type: data type of elements being received
+ *   comm: communication
+ * Descrp: Let i -> j denote the communication from node i to node j. The
+ *         order of communications for node i is i -> i + 1, i -> i + 2, ...,
+ *         i -> (i + p -1) % P.
+ *
+ * Auther: Ahmad Faraj
+ ****************************************************************************/
+int
+smpi_coll_tuned_allgather_spreading_simple(void *send_buff, int send_count,
+                                           MPI_Datatype send_type,
+                                           void *recv_buff, int recv_count,
+                                           MPI_Datatype recv_type,
+                                           MPI_Comm comm)
+{
+  MPI_Request *reqs, *req_ptr;
+  MPI_Aint extent;
+  int i, src, dst, rank, num_procs, num_reqs;
+  int tag = 1;
+  MPI_Status status;
+  char *recv_ptr = (char *) recv_buff;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
+
+  num_reqs = (2 * num_procs) - 2;
+  reqs = (MPI_Request *) xbt_malloc(num_reqs * sizeof(MPI_Request));
+  if (!reqs) {
+    printf("allgather-spreading-simple.c:40: cannot allocate memory\n");
+    MPI_Finalize();
+    exit(0);
+  }
+
+  req_ptr = reqs;
+  smpi_mpi_sendrecv(send_buff, send_count, send_type, rank, tag,
+               (char *) recv_buff + rank * recv_count * extent, recv_count,
+               recv_type, rank, tag, comm, &status);
+
+  for (i = 0; i < num_procs; i++) {
+    src = (rank + i) % num_procs;
+    if (src == rank)
+      continue;
+    *(req_ptr++) = smpi_mpi_irecv(recv_ptr + src * recv_count * extent, recv_count, recv_type,
+              src, tag, comm);
+  }
+
+  for (i = 0; i < num_procs; i++) {
+    dst = (rank + i) % num_procs;
+    if (dst == rank)
+      continue;
+    *(req_ptr++) = smpi_mpi_isend(send_buff, send_count, send_type, dst, tag, comm);
+  }
+
+  smpi_mpi_waitall(num_reqs, reqs, MPI_STATUSES_IGNORE);
+  free(reqs);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgatherv-GB.c b/src/smpi/colls/allgatherv-GB.c
new file mode 100644 (file)
index 0000000..5c643fa
--- /dev/null
@@ -0,0 +1,20 @@
+#include "colls_private.h"
+
+// Allgather - gather/bcast algorithm
+int smpi_coll_tuned_allgatherv_GB(void *send_buff, int send_count,
+                                 MPI_Datatype send_type, void *recv_buff,
+                                 int *recv_counts, int *recv_disps, MPI_Datatype recv_type,
+                                 MPI_Comm comm)
+{
+  smpi_mpi_gatherv(send_buff, send_count, send_type, recv_buff, recv_counts,
+                  recv_disps, recv_type, 0, comm);
+  int num_procs, i, current, max = 0;
+  num_procs = smpi_comm_size(comm);
+  for (i = 0; i < num_procs; i++) {
+    current = recv_disps[i] + recv_counts[i];
+    if (current > max) max = current;
+  }
+  mpi_coll_bcast_fun(recv_buff, current, recv_type, 0, comm);
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgatherv-pair.c b/src/smpi/colls/allgatherv-pair.c
new file mode 100644 (file)
index 0000000..d60e77a
--- /dev/null
@@ -0,0 +1,92 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+ * Function: allgather_pair
+ * return: int
+ *  inputs:
+ *   send_buff: send input buffer
+ *   send_count: number of elements to send
+ *   send_type: data type of elements being sent
+ *   recv_buff: receive output buffer
+ *   recv_count: number of elements to received
+ *   recv_type: data type of elements being received
+ *   comm: communication
+ * Descrp: Function works when P is power of two. In each phase of P - 1
+ *         phases, nodes in pair communicate their data.
+ * Auther: Ahmad Faraj
+ ****************************************************************************/
+int
+smpi_coll_tuned_allgatherv_pair(void *send_buff, int send_count,
+                               MPI_Datatype send_type, void *recv_buff,
+                               int *recv_counts, int *recv_disps, MPI_Datatype recv_type,
+                               MPI_Comm comm)
+{
+
+  MPI_Aint extent;
+  int i, src, dst, rank, num_procs;
+  int tag = 1;
+  MPI_Status status;
+
+  char *send_ptr = (char *) send_buff;
+  char *recv_ptr = (char *) recv_buff;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
+
+  // local send/recv
+  smpi_mpi_sendrecv(send_ptr, send_count, send_type, rank, tag,
+               recv_ptr + recv_disps[rank] * extent,
+               recv_counts[rank], recv_type, rank, tag, comm, &status);
+  for (i = 1; i < num_procs; i++) {
+    src = dst = rank ^ i;
+    smpi_mpi_sendrecv(send_ptr, send_count, send_type, dst, tag,
+                 recv_ptr + recv_disps[src] * extent, recv_counts[src], recv_type,
+                 src, tag, comm, &status);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allgatherv-ring.c b/src/smpi/colls/allgatherv-ring.c
new file mode 100644 (file)
index 0000000..4c1e14f
--- /dev/null
@@ -0,0 +1,94 @@
+#include "colls_private.h"
+
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+/*****************************************************************************
+ * Function: allgather_ring
+ * return: int
+ * inputs:
+ *   send_buff: send input buffer
+ *   send_count: number of elements to send
+ *   send_type: data type of elements being sent
+ *   recv_buff: receive output buffer
+ *   recv_count: number of elements to received
+ *   recv_type: data type of elements being received
+ *   comm: communication
+ * Descrp: Function works in P - 1 steps. In step i, node j - i -> j -> j+ i.
+ * Auther: Ahmad Faraj
+ ****************************************************************************/
+int
+smpi_coll_tuned_allgatherv_ring(void *send_buff, int send_count,
+                               MPI_Datatype send_type, void *recv_buff,
+                               int *recv_counts, int *recv_disps, MPI_Datatype recv_type,
+                               MPI_Comm comm)
+{
+
+  MPI_Aint extent;
+  int i, src, dst, rank, num_procs;
+  int tag = 1;
+  MPI_Status status;
+
+  char *sendptr = (char *) send_buff;
+  char *recvptr = (char *) recv_buff;
+
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
+
+  // local send/recv
+  smpi_mpi_sendrecv(sendptr, send_count, send_type, rank, tag,
+               recvptr + recv_disps[rank] * extent,
+               recv_counts[rank], recv_type, rank, tag, comm, &status);
+
+  for (i = 1; i < num_procs; i++) {
+    src = (rank - i + num_procs) % num_procs;
+    dst = (rank + i) % num_procs;
+    
+    smpi_mpi_sendrecv(sendptr, send_count, send_type, dst, tag,
+                 recvptr + recv_disps[src] * extent, recv_counts[src], recv_type,
+                 src, tag, comm, &status);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-NTS.c b/src/smpi/colls/allreduce-NTS.c
new file mode 100644 (file)
index 0000000..a8cf48d
--- /dev/null
@@ -0,0 +1,95 @@
+#include "colls_private.h"
+/* IMPLEMENTED BY PITCH PATARASUK 
+   Non-topoloty-specific all-reduce operation designed bandwidth optimally */
+
+/* ** NOTE **
+   Use -DMPICH2_REDUCTION if this code does not compile.
+   MPICH1 code also work on MPICH2 on our cluster and the performance are similar.
+   This code assume commutative and associative reduce operator (MPI_SUM, MPI_MAX, etc).
+*/
+
+//#include <star-reduction.c>
+
+int
+smpi_coll_tuned_allreduce_NTS(void *sbuf, void *rbuf, int rcount,
+                              MPI_Datatype dtype, MPI_Op op, MPI_Comm comm)
+{
+  int tag = 5000;
+  MPI_Status status;
+  int rank, i, size, count;
+  int send_offset, recv_offset;
+  int remainder, remainder_flag, remainder_offset;
+
+  rank = smpi_comm_rank(MPI_COMM_WORLD);
+  size = smpi_comm_size(MPI_COMM_WORLD);
+
+  /* make it compatible with all data type */
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+
+  /* when communication size is smaller than number of process (not support) */
+  if (rcount < size) {
+    return mpi_coll_allreduce_fun(sbuf, rbuf, rcount, dtype, op, comm);
+  }
+
+  /* when communication size is not divisible by number of process: 
+     call the native implementation for the remain chunk at the end of the operation */
+  if (rcount % size != 0) {
+    remainder = rcount % size;
+    remainder_flag = 1;
+    remainder_offset = (rcount / size) * size * extent;
+  } else {
+    remainder = remainder_flag = remainder_offset = 0;
+  }
+
+  /* size of each point-to-point communication is equal to the size of the whole message
+     divided by number of processes
+   */
+  count = rcount / size;
+
+  /* our ALL-REDUCE implementation
+     1. copy (partial of)send_buf to recv_buf
+     2. use logical ring reduce-scatter
+     3. use logical ring all-gather 
+   */
+
+  // copy partial data
+  send_offset = ((rank - 1 + size) % size) * count * extent;
+  recv_offset = ((rank - 1 + size) % size) * count * extent;
+  smpi_mpi_sendrecv((char *) sbuf + send_offset, count, dtype, rank, tag - 1,
+               (char *) rbuf + recv_offset, count, dtype, rank, tag - 1, comm,
+               &status);
+
+  // reduce-scatter
+  for (i = 0; i < (size - 1); i++) {
+    send_offset = ((rank - 1 - i + size) % size) * count * extent;
+    recv_offset = ((rank - 2 - i + size) % size) * count * extent;
+    smpi_mpi_sendrecv((char *) rbuf + send_offset, count, dtype, ((rank + 1) % size),
+                 tag + i, (char *) rbuf + recv_offset, count, dtype,
+                 ((rank + size - 1) % size), tag + i, comm, &status);
+
+    // compute result to rbuf+recv_offset
+    smpi_op_apply(op, (char *)sbuf + recv_offset, (char *)rbuf + recv_offset, &count, &dtype);
+  }
+
+  // all-gather
+  for (i = 0; i < (size - 1); i++) {
+    send_offset = ((rank - i + size) % size) * count * extent;
+    recv_offset = ((rank - 1 - i + size) % size) * count * extent;
+    smpi_mpi_sendrecv((char *) rbuf + send_offset, count, dtype, ((rank + 1) % size),
+                 tag + i, (char *) rbuf + recv_offset, count, dtype,
+                 ((rank + size - 1) % size), tag + i, comm, &status);
+  }
+
+  /* when communication size is not divisible by number of process: 
+     call the native implementation for the remain chunk at the end of the operation */
+  if (remainder_flag) {
+    XBT_WARN("MPI_allreduce_NTS use default MPI_allreduce.");
+    smpi_mpi_allreduce((char *) sbuf + remainder_offset,
+                         (char *) rbuf + remainder_offset, remainder, dtype, op,
+                         comm);
+    return MPI_SUCCESS;    
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-lr.c b/src/smpi/colls/allreduce-lr.c
new file mode 100644 (file)
index 0000000..81cb392
--- /dev/null
@@ -0,0 +1,100 @@
+#include "colls_private.h"
+
+/* IMPLEMENTED BY PITCH PATARASUK 
+   Non-topoloty-specific all-reduce operation designed bandwidth optimally 
+   Bug fixing by Xin Yuan, 04/04/2008
+*/
+
+/* ** NOTE **
+   Use -DMPICH2_REDUCTION if this code does not compile.
+   MPICH1 code also work on MPICH2 on our cluster and the performance are similar.
+   This code assume commutative and associative reduce operator (MPI_SUM, MPI_MAX, etc).
+*/
+
+//#include <star-reduction.c>
+
+int
+smpi_coll_tuned_allreduce_lr(void *sbuf, void *rbuf, int rcount,
+                             MPI_Datatype dtype, MPI_Op op, MPI_Comm comm)
+{
+  int tag = 5000;
+  MPI_Status status;
+  int rank, i, size, count;
+  int send_offset, recv_offset;
+  int remainder, remainder_flag, remainder_offset;
+
+  rank = smpi_comm_rank(MPI_COMM_WORLD);
+  size = smpi_comm_size(MPI_COMM_WORLD);
+
+  /* make it compatible with all data type */
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+
+  /* when communication size is smaller than number of process (not support) */
+  if (rcount < size) {
+    XBT_WARN("MPI_allreduce_lr use default MPI_allreduce.");     
+    smpi_mpi_allreduce(sbuf, rbuf, rcount, dtype, op, comm);
+    return MPI_SUCCESS; 
+  }
+
+  /* when communication size is not divisible by number of process: 
+     call the native implementation for the remain chunk at the end of the operation */
+  if (rcount % size != 0) {
+    remainder = rcount % size;
+    remainder_flag = 1;
+    remainder_offset = (rcount / size) * size * extent;
+  } else {
+    remainder = remainder_flag = remainder_offset = 0;
+  }
+
+  /* size of each point-to-point communication is equal to the size of the whole message
+     divided by number of processes
+   */
+  count = rcount / size;
+
+  /* our ALL-REDUCE implementation
+     1. copy (partial of)send_buf to recv_buf
+     2. use logical ring reduce-scatter
+     3. use logical ring all-gather 
+   */
+
+  // copy partial data
+  send_offset = ((rank - 1 + size) % size) * count * extent;
+  recv_offset = ((rank - 1 + size) % size) * count * extent;
+  smpi_mpi_sendrecv((char *) sbuf + send_offset, count, dtype, rank, tag - 1,
+               (char *) rbuf + recv_offset, count, dtype, rank, tag - 1, comm,
+               &status);
+
+  // reduce-scatter
+  for (i = 0; i < (size - 1); i++) {
+    send_offset = ((rank - 1 - i + 2 * size) % size) * count * extent;
+    recv_offset = ((rank - 2 - i + 2 * size) % size) * count * extent;
+    //    recv_offset = ((rank-i+2*size)%size)*count*extent;
+    smpi_mpi_sendrecv((char *) rbuf + send_offset, count, dtype, ((rank + 1) % size),
+                 tag + i, (char *) rbuf + recv_offset, count, dtype,
+                 ((rank + size - 1) % size), tag + i, comm, &status);
+
+    // compute result to rbuf+recv_offset
+    smpi_op_apply(op, (char *) sbuf + recv_offset, (char *) rbuf + recv_offset,
+                   &count, &dtype);
+  }
+
+  // all-gather
+  for (i = 0; i < (size - 1); i++) {
+    send_offset = ((rank - i + 2 * size) % size) * count * extent;
+    recv_offset = ((rank - 1 - i + 2 * size) % size) * count * extent;
+    smpi_mpi_sendrecv((char *) rbuf + send_offset, count, dtype, ((rank + 1) % size),
+                 tag + i, (char *) rbuf + recv_offset, count, dtype,
+                 ((rank + size - 1) % size), tag + i, comm, &status);
+  }
+
+  /* when communication size is not divisible by number of process: 
+     call the native implementation for the remain chunk at the end of the operation */
+  if (remainder_flag) {
+    return mpi_coll_allreduce_fun((char *) sbuf + remainder_offset,
+                         (char *) rbuf + remainder_offset, remainder, dtype, op,
+                         comm);
+  }
+
+  return 0;
+}
diff --git a/src/smpi/colls/allreduce-rab-rdb.c b/src/smpi/colls/allreduce-rab-rdb.c
new file mode 100644 (file)
index 0000000..9d5ee9c
--- /dev/null
@@ -0,0 +1,189 @@
+#include "colls_private.h"
+
+int smpi_coll_tuned_allreduce_rab_rdb(void *sbuff, void *rbuff, int count,
+                                      MPI_Datatype dtype, MPI_Op op,
+                                      MPI_Comm comm)
+{
+  int nprocs, rank, tag = 543;
+  int mask, dst, pof2, newrank, rem, newdst, i,
+      send_idx, recv_idx, last_idx, send_cnt, recv_cnt, *cnts, *disps;
+  MPI_Aint extent;
+  MPI_Status status;
+  void *tmp_buf = NULL;
+
+  nprocs = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  smpi_datatype_copy(sbuff, count, dtype, rbuff, count, dtype);
+
+  // find nearest power-of-two less than or equal to comm_size
+  pof2 = 1;
+  while (pof2 <= nprocs)
+    pof2 <<= 1;
+  pof2 >>= 1;
+
+  rem = nprocs - pof2;
+
+  // In the non-power-of-two case, all even-numbered
+  // processes of rank < 2*rem send their data to
+  // (rank+1). These even-numbered processes no longer
+  // participate in the algorithm until the very end. The
+  // remaining processes form a nice power-of-two. 
+
+  if (rank < 2 * rem) {
+    // even       
+    if (rank % 2 == 0) {
+
+      smpi_mpi_send(rbuff, count, dtype, rank + 1, tag, comm);
+
+      // temporarily set the rank to -1 so that this
+      // process does not pariticipate in recursive
+      // doubling
+      newrank = -1;
+    } else                      // odd
+    {
+      smpi_mpi_recv(tmp_buf, count, dtype, rank - 1, tag, comm, &status);
+      // do the reduction on received data. since the
+      // ordering is right, it doesn't matter whether
+      // the operation is commutative or not.
+       smpi_op_apply(op, tmp_buf, rbuff, &count, &dtype);
+
+      // change the rank 
+      newrank = rank / 2;
+    }
+  }
+
+  else                          // rank >= 2 * rem 
+    newrank = rank - rem;
+
+  // If op is user-defined or count is less than pof2, use
+  // recursive doubling algorithm. Otherwise do a reduce-scatter
+  // followed by allgather. (If op is user-defined,
+  // derived datatypes are allowed and the user could pass basic
+  // datatypes on one process and derived on another as long as
+  // the type maps are the same. Breaking up derived
+  // datatypes to do the reduce-scatter is tricky, therefore
+  // using recursive doubling in that case.) 
+
+  if (newrank != -1) {
+    // do a reduce-scatter followed by allgather. for the
+    // reduce-scatter, calculate the count that each process receives
+    // and the displacement within the buffer 
+
+    cnts = (int *) xbt_malloc(pof2 * sizeof(int));
+    disps = (int *) xbt_malloc(pof2 * sizeof(int));
+
+    for (i = 0; i < (pof2 - 1); i++)
+      cnts[i] = count / pof2;
+    cnts[pof2 - 1] = count - (count / pof2) * (pof2 - 1);
+
+    disps[0] = 0;
+    for (i = 1; i < pof2; i++)
+      disps[i] = disps[i - 1] + cnts[i - 1];
+
+    mask = 0x1;
+    send_idx = recv_idx = 0;
+    last_idx = pof2;
+    while (mask < pof2) {
+      newdst = newrank ^ mask;
+      // find real rank of dest 
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      send_cnt = recv_cnt = 0;
+      if (newrank < newdst) {
+        send_idx = recv_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < last_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < send_idx; i++)
+          recv_cnt += cnts[i];
+      } else {
+        recv_idx = send_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < recv_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < last_idx; i++)
+          recv_cnt += cnts[i];
+      }
+
+      // Send data from recvbuf. Recv into tmp_buf 
+      smpi_mpi_sendrecv((char *) rbuff + disps[send_idx] * extent, send_cnt,
+                   dtype, dst, tag,
+                   (char *) tmp_buf + disps[recv_idx] * extent, recv_cnt,
+                   dtype, dst, tag, comm, &status);
+
+      // tmp_buf contains data received in this step.
+      // recvbuf contains data accumulated so far 
+
+      // This algorithm is used only for predefined ops
+      // and predefined ops are always commutative.
+      smpi_op_apply(op, (char *) tmp_buf + disps[recv_idx] * extent,
+                        (char *) rbuff + disps[recv_idx] * extent, &recv_cnt, &dtype);
+
+      // update send_idx for next iteration 
+      send_idx = recv_idx;
+      mask <<= 1;
+
+      // update last_idx, but not in last iteration because the value
+      // is needed in the allgather step below. 
+      if (mask < pof2)
+        last_idx = recv_idx + pof2 / mask;
+    }
+
+    // now do the allgather 
+
+    mask >>= 1;
+    while (mask > 0) {
+      newdst = newrank ^ mask;
+      // find real rank of dest
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      send_cnt = recv_cnt = 0;
+      if (newrank < newdst) {
+        // update last_idx except on first iteration 
+        if (mask != pof2 / 2)
+          last_idx = last_idx + pof2 / (mask * 2);
+
+        recv_idx = send_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < recv_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < last_idx; i++)
+          recv_cnt += cnts[i];
+      } else {
+        recv_idx = send_idx - pof2 / (mask * 2);
+        for (i = send_idx; i < last_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < send_idx; i++)
+          recv_cnt += cnts[i];
+      }
+
+      smpi_mpi_sendrecv((char *) rbuff + disps[send_idx] * extent, send_cnt,
+                   dtype, dst, tag,
+                   (char *) rbuff + disps[recv_idx] * extent, recv_cnt,
+                   dtype, dst, tag, comm, &status);
+
+      if (newrank > newdst)
+        send_idx = recv_idx;
+
+      mask >>= 1;
+    }
+
+    free(cnts);
+    free(disps);
+
+  }
+  // In the non-power-of-two case, all odd-numbered processes of
+  // rank < 2 * rem send the result to (rank-1), the ranks who didn't
+  // participate above.
+
+  if (rank < 2 * rem) {
+    if (rank % 2)               // odd 
+      smpi_mpi_send(rbuff, count, dtype, rank - 1, tag, comm);
+    else                        // even 
+      smpi_mpi_recv(rbuff, count, dtype, rank + 1, tag, comm, &status);
+  }
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-rab-reduce-scatter.c b/src/smpi/colls/allreduce-rab-reduce-scatter.c
new file mode 100644 (file)
index 0000000..5650ef2
--- /dev/null
@@ -0,0 +1,521 @@
+#include "colls_private.h"
+#ifndef REDUCE_STUFF
+#define REDUCE_STUFF
+/*****************************************************************************
+
+Copyright (c) 2006, Ahmad Faraj & Xin Yuan,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the name of the Florida State University nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  *************************************************************************
+  *     Any results obtained from executing this software require the     *
+  *     acknowledgment and citation of the software and its owners.       *
+  *     The full citation is given below:                                 *
+  *                                                                       *
+  *     A. Faraj and X. Yuan. "Automatic Generation and Tuning of MPI     *
+  *     Collective Communication Routines." The 19th ACM International    *
+  *     Conference on Supercomputing (ICS), Cambridge, Massachusetts,     *
+  *     June 20-22, 2005.                                                 *
+  *************************************************************************
+
+*****************************************************************************/
+
+extern MPI_User_function *MPIR_Op_table[];
+
+
+/* -*- Mode: C; c-basic-offset:4 ; -*- */
+/*  $Id: mpich-stuff.h,v 1.1 2005/08/22 19:50:21 faraj Exp $
+ *
+ *  (C) 2001 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#ifndef _MPICH_STUFF_H
+#define _MPICH_STUFF_H
+
+/*TOpaqOverview.tex
+  MPI Opaque Objects:
+
+  MPI Opaque objects such as 'MPI_Comm' or 'MPI_Datatype' are specified by 
+  integers (in the MPICH2 implementation); the MPI standard calls these
+  handles.  
+  Out of range values are invalid; the value 0 is reserved.
+  For most (with the possible exception of 
+  'MPI_Request' for performance reasons) MPI Opaque objects, the integer
+  encodes both the kind of object (allowing runtime tests to detect a datatype
+  passed where a communicator is expected) and important properties of the 
+  object.  Even the 'MPI_xxx_NULL' values should be encoded so that 
+  different null handles can be distinguished.  The details of the encoding
+  of the handles is covered in more detail in the MPICH2 Design Document.
+  For the most part, the ADI uses pointers to the underlying structures
+  rather than the handles themselves.  However, each structure contains an 
+  'handle' field that is the corresponding integer handle for the MPI object.
+
+  MPID objects (objects used within the implementation of MPI) are not opaque.
+
+  T*/
+
+/* Known MPI object types.  These are used for both the error handlers 
+   and for the handles.  This is a 4 bit value.  0 is reserved for so 
+   that all-zero handles can be flagged as an error. */
+/*E
+  MPID_Object_kind - Object kind (communicator, window, or file)
+
+  Notes:
+  This enum is used by keyvals and errhandlers to indicate the type of
+  object for which MPI opaque types the data is valid.  These are defined
+  as bits to allow future expansion to the case where an object is value for
+  multiple types (for example, we may want a universal error handler for 
+  errors return).  This is also used to indicate the type of MPI object a 
+  MPI handle represents.  It is an enum because only this applies only the
+  the MPI objects.
+
+  Module:
+  Attribute-DS
+  E*/
+typedef enum MPID_Object_kind {
+  MPID_COMM = 0x1,
+  MPID_GROUP = 0x2,
+  MPID_DATATYPE = 0x3,
+  MPID_FILE = 0x4,
+  MPID_ERRHANDLER = 0x5,
+  MPID_OP = 0x6,
+  MPID_INFO = 0x7,
+  MPID_WIN = 0x8,
+  MPID_KEYVAL = 0x9,
+  MPID_ATTR = 0xa,
+  MPID_REQUEST = 0xb
+} MPID_Object_kind;
+/* The above objects should correspond to MPI objects only. */
+#define HANDLE_MPI_KIND_SHIFT 26
+#define HANDLE_GET_MPI_KIND(a) ( ((a)&0x3c000000) >> HANDLE_MPI_KIND_SHIFT )
+
+/* Handle types.  These are really 2 bits */
+#define HANDLE_KIND_INVALID  0x0
+#define HANDLE_KIND_BUILTIN  0x1
+#define HANDLE_KIND_DIRECT   0x2
+#define HANDLE_KIND_INDIRECT 0x3
+/* Mask assumes that ints are at least 4 bytes */
+#define HANDLE_KIND_MASK 0xc0000000
+#define HANDLE_KIND_SHIFT 30
+#define HANDLE_GET_KIND(a) (((a)&HANDLE_KIND_MASK)>>HANDLE_KIND_SHIFT)
+#define HANDLE_SET_KIND(a,kind) ((a)|((kind)<<HANDLE_KIND_SHIFT))
+
+/* For indirect, the remainder of the handle has a block and index */
+#define HANDLE_INDIRECT_SHIFT 16
+#define HANDLE_BLOCK(a) (((a)& 0x03FF0000) >> HANDLE_INDIRECT_SHIFT)
+#define HANDLE_BLOCK_INDEX(a) ((a) & 0x0000FFFF)
+
+/* Handle block is between 1 and 1024 *elements* */
+#define HANDLE_BLOCK_SIZE 256
+/* Index size is bewtween 1 and 65536 *elements* */
+#define HANDLE_BLOCK_INDEX_SIZE 1024
+
+/* For direct, the remainder of the handle is the index into a predefined 
+   block */
+#define HANDLE_MASK 0x03FFFFFF
+#define HANDLE_INDEX(a) ((a)& HANDLE_MASK)
+
+/* ALL objects have the handle as the first value. */
+/* Inactive (unused and stored on the appropriate avail list) objects 
+   have MPIU_Handle_common as the head */
+typedef struct MPIU_Handle_common {
+  int handle;
+  volatile int ref_count;       /* This field is used to indicate that the
+                                   object is not in use (see, e.g., 
+                                   MPID_Comm_valid_ptr) */
+  void *next;                   /* Free handles use this field to point to the next
+                                   free object */
+} MPIU_Handle_common;
+
+/* All *active* (in use) objects have the handle as the first value; objects
+   with referene counts have the reference count as the second value.
+   See MPIU_Object_add_ref and MPIU_Object_release_ref. */
+typedef struct MPIU_Handle_head {
+  int handle;
+  volatile int ref_count;
+} MPIU_Handle_head;
+
+/* This type contains all of the data, except for the direct array,
+   used by the object allocators. */
+typedef struct MPIU_Object_alloc_t {
+  MPIU_Handle_common *avail;    /* Next available object */
+  int initialized;              /* */
+  void *(*indirect)[];          /* Pointer to indirect object blocks */
+  int indirect_size;            /* Number of allocated indirect blocks */
+  MPID_Object_kind kind;        /* Kind of object this is for */
+  int size;                     /* Size of an individual object */
+  void *direct;                 /* Pointer to direct block, used 
+                                   for allocation */
+  int direct_size;              /* Size of direct block */
+} MPIU_Object_alloc_t;
+extern void *MPIU_Handle_obj_alloc(MPIU_Object_alloc_t *);
+extern void MPIU_Handle_obj_alloc_start(MPIU_Object_alloc_t *);
+extern void MPIU_Handle_obj_alloc_complete(MPIU_Object_alloc_t *, int init);
+extern void MPIU_Handle_obj_free(MPIU_Object_alloc_t *, void *);
+void *MPIU_Handle_get_ptr_indirect(int, MPIU_Object_alloc_t *);
+extern void *MPIU_Handle_direct_init(void *direct, int direct_size,
+                                     int obj_size, int handle_type);
+#endif
+#define MPID_Getb_ptr(kind,a,bmsk,ptr)                                  \
+{                                                                       \
+   switch (HANDLE_GET_KIND(a)) {                                        \
+      case HANDLE_KIND_BUILTIN:                                         \
+          ptr=MPID_##kind##_builtin+((a)&(bmsk));                       \
+          break;                                                        \
+      case HANDLE_KIND_DIRECT:                                          \
+          ptr=MPID_##kind##_direct+HANDLE_INDEX(a);                     \
+          break;                                                        \
+      case HANDLE_KIND_INDIRECT:                                        \
+          ptr=((MPID_##kind*)                                           \
+               MPIU_Handle_get_ptr_indirect(a,&MPID_##kind##_mem));     \
+          break;                                                        \
+      case HANDLE_KIND_INVALID:                                         \
+      default:                                                         \
+          ptr=0;                                                       \
+          break;                                                       \
+    }                                                                   \
+}
+
+
+
+#define MPID_Op_get_ptr(a,ptr)         MPID_Getb_ptr(Op,a,0x000000ff,ptr)
+typedef enum MPID_Lang_t { MPID_LANG_C
+#ifdef HAVE_FORTRAN_BINDING
+      , MPID_LANG_FORTRAN, MPID_LANG_FORTRAN90
+#endif
+#ifdef HAVE_CXX_BINDING
+      , MPID_LANG_CXX
+#endif
+} MPID_Lang_t;
+/* Reduction and accumulate operations */
+/*E
+  MPID_Op_kind - Enumerates types of MPI_Op types
+
+  Notes:
+  These are needed for implementing 'MPI_Accumulate', since only predefined
+  operations are allowed for that operation.  
+
+  A gap in the enum values was made allow additional predefined operations
+  to be inserted.  This might include future additions to MPI or experimental
+  extensions (such as a Read-Modify-Write operation).
+
+  Module:
+  Collective-DS
+  E*/
+typedef enum MPID_Op_kind { MPID_OP_MAX = 1, MPID_OP_MIN = 2,
+  MPID_OP_SUM = 3, MPID_OP_PROD = 4,
+  MPID_OP_LAND = 5, MPID_OP_BAND = 6, MPID_OP_LOR = 7, MPID_OP_BOR = 8,
+  MPID_OP_LXOR = 9, MPID_OP_BXOR = 10, MPID_OP_MAXLOC = 11,
+  MPID_OP_MINLOC = 12, MPID_OP_REPLACE = 13,
+  MPID_OP_USER_NONCOMMUTE = 32, MPID_OP_USER = 33
+} MPID_Op_kind;
+
+/*S
+  MPID_User_function - Definition of a user function for MPI_Op types.
+
+  Notes:
+  This includes a 'const' to make clear which is the 'in' argument and 
+  which the 'inout' argument, and to indicate that the 'count' and 'datatype'
+  arguments are unchanged (they are addresses in an attempt to allow 
+  interoperation with Fortran).  It includes 'restrict' to emphasize that 
+  no overlapping operations are allowed.
+
+  We need to include a Fortran version, since those arguments will
+  have type 'MPI_Fint *' instead.  We also need to add a test to the
+  test suite for this case; in fact, we need tests for each of the handle
+  types to ensure that the transfered handle works correctly.
+
+  This is part of the collective module because user-defined operations
+  are valid only for the collective computation routines and not for 
+  RMA accumulate.
+
+  Yes, the 'restrict' is in the correct location.  C compilers that 
+  support 'restrict' should be able to generate code that is as good as a
+  Fortran compiler would for these functions.
+
+  We should note on the manual pages for user-defined operations that
+  'restrict' should be used when available, and that a cast may be 
+  required when passing such a function to 'MPI_Op_create'.
+
+  Question:
+  Should each of these function types have an associated typedef?
+
+  Should there be a C++ function here?
+
+  Module:
+  Collective-DS
+  S*/
+typedef union MPID_User_function {
+  void (*c_function) (const void *, void *, const int *, const MPI_Datatype *);
+  void (*f77_function) (const void *, void *,
+                        const MPI_Fint *, const MPI_Fint *);
+} MPID_User_function;
+/* FIXME: Should there be "restrict" in the definitions above, e.g., 
+   (*c_function)( const void restrict * , void restrict *, ... )? */
+
+/*S
+  MPID_Op - MPI_Op structure
+
+  Notes:
+  All of the predefined functions are commutative.  Only user functions may 
+  be noncummutative, so there are two separate op types for commutative and
+  non-commutative user-defined operations.
+
+  Operations do not require reference counts because there are no nonblocking
+  operations that accept user-defined operations.  Thus, there is no way that
+  a valid program can free an 'MPI_Op' while it is in use.
+
+  Module:
+  Collective-DS
+  S*/
+typedef struct MPID_Op {
+  int handle;                   /* value of MPI_Op for this structure */
+  volatile int ref_count;
+  MPID_Op_kind kind;
+  MPID_Lang_t language;
+  MPID_User_function function;
+} MPID_Op;
+#define MPID_OP_N_BUILTIN 14
+extern MPID_Op MPID_Op_builtin[MPID_OP_N_BUILTIN];
+extern MPID_Op MPID_Op_direct[];
+extern MPIU_Object_alloc_t MPID_Op_mem;
+
+/*****************************************************************************
+
+* Function: get_op_func
+
+* return: Pointer to MPI_User_function
+
+* inputs:
+   op: operator (max, min, etc)
+
+   * Descrp: Function returns the function associated with current operator
+   * op.
+
+   * Auther: AHMAD FARAJ
+
+****************************************************************************/
+MPI_User_function *get_op_func(MPI_Op op)
+{
+
+  if (HANDLE_GET_KIND(op) == HANDLE_KIND_BUILTIN)
+    return MPIR_Op_table[op % 16 - 1];
+  return NULL;
+}
+
+#endif
+
+
+int smpi_coll_tuned_allreduce_rab_reduce_scatter(void *sbuff, void *rbuff,
+                                                 int count, MPI_Datatype dtype,
+                                                 MPI_Op op, MPI_Comm comm)
+{
+  int nprocs, rank, type_size, tag = 543;
+  int mask, dst, pof2, newrank, rem, newdst, i,
+      send_idx, recv_idx, last_idx, send_cnt, recv_cnt, *cnts, *disps;
+  MPI_Aint lb, extent;
+  MPI_Status status;
+  void *tmp_buf = NULL;
+  MPI_User_function *func = get_op_func(op);
+  nprocs = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  MPIR_Localcopy(sbuff, count, dtype, rbuff, count, dtype);
+
+  type_size = smpi_datatype_size(dtype);
+
+  // find nearest power-of-two less than or equal to comm_size
+  pof2 = 1;
+  while (pof2 <= nprocs)
+    pof2 <<= 1;
+  pof2 >>= 1;
+
+  rem = nprocs - pof2;
+
+  // In the non-power-of-two case, all even-numbered
+  // processes of rank < 2*rem send their data to
+  // (rank+1). These even-numbered processes no longer
+  // participate in the algorithm until the very end. The
+  // remaining processes form a nice power-of-two. 
+
+  if (rank < 2 * rem) {
+    // even       
+    if (rank % 2 == 0) {
+
+      MPIC_Send(rbuff, count, dtype, rank + 1, tag, comm);
+
+      // temporarily set the rank to -1 so that this
+      // process does not pariticipate in recursive
+      // doubling
+      newrank = -1;
+    } else                      // odd
+    {
+      MPIC_Recv(tmp_buf, count, dtype, rank - 1, tag, comm, &status);
+      // do the reduction on received data. since the
+      // ordering is right, it doesn't matter whether
+      // the operation is commutative or not.
+      (*func) (tmp_buf, rbuff, &count, &dtype);
+
+      // change the rank 
+      newrank = rank / 2;
+    }
+  }
+
+  else                          // rank >= 2 * rem 
+    newrank = rank - rem;
+
+  // If op is user-defined or count is less than pof2, use
+  // recursive doubling algorithm. Otherwise do a reduce-scatter
+  // followed by allgather. (If op is user-defined,
+  // derived datatypes are allowed and the user could pass basic
+  // datatypes on one process and derived on another as long as
+  // the type maps are the same. Breaking up derived
+  // datatypes to do the reduce-scatter is tricky, therefore
+  // using recursive doubling in that case.) 
+
+  if (newrank != -1) {
+    // do a reduce-scatter followed by allgather. for the
+    // reduce-scatter, calculate the count that each process receives
+    // and the displacement within the buffer 
+
+    cnts = (int *) xbt_malloc(pof2 * sizeof(int));
+    disps = (int *) xbt_malloc(pof2 * sizeof(int));
+
+    for (i = 0; i < (pof2 - 1); i++)
+      cnts[i] = count / pof2;
+    cnts[pof2 - 1] = count - (count / pof2) * (pof2 - 1);
+
+    disps[0] = 0;
+    for (i = 1; i < pof2; i++)
+      disps[i] = disps[i - 1] + cnts[i - 1];
+
+    mask = 0x1;
+    send_idx = recv_idx = 0;
+    last_idx = pof2;
+    while (mask < pof2) {
+      newdst = newrank ^ mask;
+      // find real rank of dest 
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      send_cnt = recv_cnt = 0;
+      if (newrank < newdst) {
+        send_idx = recv_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < last_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < send_idx; i++)
+          recv_cnt += cnts[i];
+      } else {
+        recv_idx = send_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < recv_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < last_idx; i++)
+          recv_cnt += cnts[i];
+      }
+
+      // Send data from recvbuf. Recv into tmp_buf 
+      MPIC_Sendrecv((char *) rbuff + disps[send_idx] * extent, send_cnt,
+                    dtype, dst, tag,
+                    (char *) tmp_buf + disps[recv_idx] * extent, recv_cnt,
+                    dtype, dst, tag, comm, &status);
+
+      // tmp_buf contains data received in this step.
+      // recvbuf contains data accumulated so far 
+
+      // This algorithm is used only for predefined ops
+      // and predefined ops are always commutative.
+      (*func) ((char *) tmp_buf + disps[recv_idx] * extent,
+               (char *) rbuff + disps[recv_idx] * extent, &recv_cnt, &dtype);
+
+      // update send_idx for next iteration 
+      send_idx = recv_idx;
+      mask <<= 1;
+
+      // update last_idx, but not in last iteration because the value
+      // is needed in the allgather step below. 
+      if (mask < pof2)
+        last_idx = recv_idx + pof2 / mask;
+    }
+
+    // now do the allgather 
+
+    mask >>= 1;
+    while (mask > 0) {
+      newdst = newrank ^ mask;
+      // find real rank of dest
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      send_cnt = recv_cnt = 0;
+      if (newrank < newdst) {
+        // update last_idx except on first iteration 
+        if (mask != pof2 / 2)
+          last_idx = last_idx + pof2 / (mask * 2);
+
+        recv_idx = send_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < recv_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < last_idx; i++)
+          recv_cnt += cnts[i];
+      } else {
+        recv_idx = send_idx - pof2 / (mask * 2);
+        for (i = send_idx; i < last_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < send_idx; i++)
+          recv_cnt += cnts[i];
+      }
+
+      MPIC_Sendrecv((char *) rbuff + disps[send_idx] * extent, send_cnt,
+                    dtype, dst, tag,
+                    (char *) rbuff + disps[recv_idx] * extent, recv_cnt,
+                    dtype, dst, tag, comm, &status);
+
+      if (newrank > newdst)
+        send_idx = recv_idx;
+
+      mask >>= 1;
+    }
+
+    free(cnts);
+    free(disps);
+
+  }
+  // In the non-power-of-two case, all odd-numbered processes of
+  // rank < 2 * rem send the result to (rank-1), the ranks who didn't
+  // participate above.
+
+  if (rank < 2 * rem) {
+    if (rank % 2)               // odd 
+      MPIC_Send(rbuff, count, dtype, rank - 1, tag, comm);
+    else                        // even 
+      MPIC_Recv(rbuff, count, dtype, rank + 1, tag, comm, &status);
+  }
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-rab-rsag.c b/src/smpi/colls/allreduce-rab-rsag.c
new file mode 100644 (file)
index 0000000..34e23d6
--- /dev/null
@@ -0,0 +1,191 @@
+#include "colls_private.h"
+//#include <star-reduction.c>
+
+int smpi_coll_tuned_allreduce_rab_rsag(void *sbuff, void *rbuff, int count,
+                                       MPI_Datatype dtype, MPI_Op op,
+                                       MPI_Comm comm)
+{
+  int nprocs, rank, tag = 543;
+  int mask, dst, pof2, newrank, rem, newdst, i,
+      send_idx, recv_idx, last_idx, send_cnt, recv_cnt, *cnts, *disps;
+  MPI_Aint extent;
+  MPI_Status status;
+  void *tmp_buf = NULL;
+  nprocs = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  smpi_mpi_sendrecv(sbuff, count, dtype, rank, tag, rbuff, count, dtype, rank, tag,
+               comm, &status);
+
+  // find nearest power-of-two less than or equal to comm_size
+  pof2 = 1;
+  while (pof2 <= nprocs)
+    pof2 <<= 1;
+  pof2 >>= 1;
+
+  rem = nprocs - pof2;
+
+  // In the non-power-of-two case, all even-numbered
+  // processes of rank < 2*rem send their data to
+  // (rank+1). These even-numbered processes no longer
+  // participate in the algorithm until the very end. The
+  // remaining processes form a nice power-of-two. 
+
+  if (rank < 2 * rem) {
+    // even       
+    if (rank % 2 == 0) {
+
+      smpi_mpi_send(rbuff, count, dtype, rank + 1, tag, comm);
+
+      // temporarily set the rank to -1 so that this
+      // process does not pariticipate in recursive
+      // doubling
+      newrank = -1;
+    } else                      // odd
+    {
+      smpi_mpi_recv(tmp_buf, count, dtype, rank - 1, tag, comm, &status);
+      // do the reduction on received data. since the
+      // ordering is right, it doesn't matter whether
+      // the operation is commutative or not.
+      smpi_op_apply(op, tmp_buf, rbuff, &count, &dtype);
+
+      // change the rank 
+      newrank = rank / 2;
+    }
+  }
+
+  else                          // rank >= 2 * rem 
+    newrank = rank - rem;
+
+  // If op is user-defined or count is less than pof2, use
+  // recursive doubling algorithm. Otherwise do a reduce-scatter
+  // followed by allgather. (If op is user-defined,
+  // derived datatypes are allowed and the user could pass basic
+  // datatypes on one process and derived on another as long as
+  // the type maps are the same. Breaking up derived
+  // datatypes to do the reduce-scatter is tricky, therefore
+  // using recursive doubling in that case.) 
+
+  if (newrank != -1) {
+    // do a reduce-scatter followed by allgather. for the
+    // reduce-scatter, calculate the count that each process receives
+    // and the displacement within the buffer 
+
+    cnts = (int *) xbt_malloc(pof2 * sizeof(int));
+    disps = (int *) xbt_malloc(pof2 * sizeof(int));
+
+    for (i = 0; i < (pof2 - 1); i++)
+      cnts[i] = count / pof2;
+    cnts[pof2 - 1] = count - (count / pof2) * (pof2 - 1);
+
+    disps[0] = 0;
+    for (i = 1; i < pof2; i++)
+      disps[i] = disps[i - 1] + cnts[i - 1];
+
+    mask = 0x1;
+    send_idx = recv_idx = 0;
+    last_idx = pof2;
+    while (mask < pof2) {
+      newdst = newrank ^ mask;
+      // find real rank of dest 
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      send_cnt = recv_cnt = 0;
+      if (newrank < newdst) {
+        send_idx = recv_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < last_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < send_idx; i++)
+          recv_cnt += cnts[i];
+      } else {
+        recv_idx = send_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < recv_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < last_idx; i++)
+          recv_cnt += cnts[i];
+      }
+
+      // Send data from recvbuf. Recv into tmp_buf 
+      smpi_mpi_sendrecv((char *) rbuff + disps[send_idx] * extent, send_cnt,
+                   dtype, dst, tag,
+                   (char *) tmp_buf + disps[recv_idx] * extent, recv_cnt,
+                   dtype, dst, tag, comm, &status);
+
+      // tmp_buf contains data received in this step.
+      // recvbuf contains data accumulated so far 
+
+      // This algorithm is used only for predefined ops
+      // and predefined ops are always commutative.
+      smpi_op_apply(op, (char *) tmp_buf + disps[recv_idx] * extent,
+                     (char *) rbuff + disps[recv_idx] * extent,
+                     &recv_cnt, &dtype);
+
+      // update send_idx for next iteration 
+      send_idx = recv_idx;
+      mask <<= 1;
+
+      // update last_idx, but not in last iteration because the value
+      // is needed in the allgather step below. 
+      if (mask < pof2)
+        last_idx = recv_idx + pof2 / mask;
+    }
+
+    // now do the allgather 
+
+    mask >>= 1;
+    while (mask > 0) {
+      newdst = newrank ^ mask;
+      // find real rank of dest
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      send_cnt = recv_cnt = 0;
+      if (newrank < newdst) {
+        // update last_idx except on first iteration 
+        if (mask != pof2 / 2)
+          last_idx = last_idx + pof2 / (mask * 2);
+
+        recv_idx = send_idx + pof2 / (mask * 2);
+        for (i = send_idx; i < recv_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < last_idx; i++)
+          recv_cnt += cnts[i];
+      } else {
+        recv_idx = send_idx - pof2 / (mask * 2);
+        for (i = send_idx; i < last_idx; i++)
+          send_cnt += cnts[i];
+        for (i = recv_idx; i < send_idx; i++)
+          recv_cnt += cnts[i];
+      }
+
+      smpi_mpi_sendrecv((char *) rbuff + disps[send_idx] * extent, send_cnt,
+                   dtype, dst, tag,
+                   (char *) rbuff + disps[recv_idx] * extent, recv_cnt,
+                   dtype, dst, tag, comm, &status);
+
+      if (newrank > newdst)
+        send_idx = recv_idx;
+
+      mask >>= 1;
+    }
+
+    free(cnts);
+    free(disps);
+
+  }
+  // In the non-power-of-two case, all odd-numbered processes of
+  // rank < 2 * rem send the result to (rank-1), the ranks who didn't
+  // participate above.
+
+  if (rank < 2 * rem) {
+    if (rank % 2)               // odd 
+      smpi_mpi_send(rbuff, count, dtype, rank - 1, tag, comm);
+    else                        // even 
+      smpi_mpi_recv(rbuff, count, dtype, rank + 1, tag, comm, &status);
+  }
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-rab1.c b/src/smpi/colls/allreduce-rab1.c
new file mode 100644 (file)
index 0000000..ae72f74
--- /dev/null
@@ -0,0 +1,101 @@
+#include "colls_private.h"
+//#include <star-reduction.c>
+
+// NP pow of 2 for now
+int smpi_coll_tuned_allreduce_rab1(void *sbuff, void *rbuff,
+                                   int count, MPI_Datatype dtype,
+                                   MPI_Op op, MPI_Comm comm)
+{
+  MPI_Status status;
+  MPI_Aint extent;
+  int tag = 4321, rank, nprocs, send_size, newcnt, share;
+  int pof2 = 1, mask, send_idx, recv_idx, dst, send_cnt, recv_cnt;
+
+  void *recv, *tmp_buf;
+
+  rank = smpi_comm_rank(comm);
+  nprocs = smpi_comm_size(comm);
+
+  extent = smpi_datatype_get_extent(dtype);
+
+  pof2 = 1;
+  while (pof2 <= nprocs)
+    pof2 <<= 1;
+  pof2 >>= 1;
+
+  mask = 1;
+  send_idx = recv_idx = 0;
+
+  // uneven count
+  if ((count % nprocs)) {
+    send_size = (count + nprocs) / nprocs;
+    newcnt = send_size * nprocs;
+
+    recv = (void *) xbt_malloc(extent * newcnt);
+    tmp_buf = (void *) xbt_malloc(extent * newcnt);
+    memcpy(recv, sbuff, extent * count);
+
+
+    mask = pof2 / 2;
+    share = newcnt / pof2;
+    while (mask > 0) {
+      dst = rank ^ mask;
+      send_cnt = recv_cnt = newcnt / (pof2 / mask);
+
+      if (rank < dst)
+        send_idx = recv_idx + (mask * share);
+      else
+        recv_idx = send_idx + (mask * share);
+
+      smpi_mpi_sendrecv((char *) recv + send_idx * extent, send_cnt, dtype, dst, tag,
+                   tmp_buf, recv_cnt, dtype, dst, tag, comm, &status);
+
+      smpi_op_apply(op, tmp_buf, (char *) recv + recv_idx * extent, &recv_cnt,
+                     &dtype);
+
+      // update send_idx for next iteration 
+      send_idx = recv_idx;
+      mask >>= 1;
+    }
+
+    memcpy(tmp_buf, (char *) recv + recv_idx * extent, recv_cnt * extent);
+    mpi_coll_allgather_fun(tmp_buf, recv_cnt, dtype, recv, recv_cnt, dtype, comm);
+
+    memcpy(rbuff, recv, count * extent);
+    free(recv);
+    free(tmp_buf);
+
+  }
+
+  else {
+    tmp_buf = (void *) xbt_malloc(extent * count);
+    memcpy(rbuff, sbuff, count * extent);
+    mask = pof2 / 2;
+    share = count / pof2;
+    while (mask > 0) {
+      dst = rank ^ mask;
+      send_cnt = recv_cnt = count / (pof2 / mask);
+
+      if (rank < dst)
+        send_idx = recv_idx + (mask * share);
+      else
+        recv_idx = send_idx + (mask * share);
+
+      smpi_mpi_sendrecv((char *) rbuff + send_idx * extent, send_cnt, dtype, dst,
+                   tag, tmp_buf, recv_cnt, dtype, dst, tag, comm, &status);
+
+      smpi_op_apply(op, tmp_buf, (char *) rbuff + recv_idx * extent, &recv_cnt,
+                     &dtype);
+
+      // update send_idx for next iteration 
+      send_idx = recv_idx;
+      mask >>= 1;
+    }
+
+    memcpy(tmp_buf, (char *) rbuff + recv_idx * extent, recv_cnt * extent);
+    mpi_coll_allgather_fun(tmp_buf, recv_cnt, dtype, rbuff, recv_cnt, dtype, comm);
+    free(tmp_buf);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-rab2.c b/src/smpi/colls/allreduce-rab2.c
new file mode 100644 (file)
index 0000000..982933c
--- /dev/null
@@ -0,0 +1,78 @@
+#include "colls_private.h"
+//#include <star-reduction.c>
+
+// this requires that count >= NP
+int smpi_coll_tuned_allreduce_rab2(void *sbuff, void *rbuff,
+                                   int count, MPI_Datatype dtype,
+                                   MPI_Op op, MPI_Comm comm)
+{
+  MPI_Aint s_extent;
+  int i, rank, nprocs;
+  int nbytes, send_size, s_offset, r_offset;
+  void *recv, *send, *tmp;
+  /*
+     #ifdef MPICH2_REDUCTION
+     MPI_User_function * uop = MPIR_Op_table[op % 16 - 1];
+     #else
+     MPI_User_function *uop;
+     struct MPIR_OP *op_ptr;
+     op_ptr = MPIR_ToPointer(op);
+     uop  = op_ptr->op;
+     #endif
+   */
+  rank = smpi_comm_rank(comm);
+  nprocs = smpi_comm_size(comm);
+
+
+  s_extent = smpi_datatype_get_extent(dtype);
+
+  // uneven count
+  if (count % nprocs) {
+    if (count < nprocs)
+      send_size = nprocs;
+    else
+      send_size = (count + nprocs) / nprocs;
+    nbytes = send_size * s_extent;
+
+    send = (void *) xbt_malloc(s_extent * send_size * nprocs);
+    recv = (void *) xbt_malloc(s_extent * send_size * nprocs);
+    tmp = (void *) xbt_malloc(nbytes);
+
+    memcpy(send, sbuff, s_extent * count);
+
+    mpi_coll_alltoall_fun(send, send_size, dtype, recv, send_size, dtype, comm);
+
+    memcpy(tmp, recv, nbytes);
+
+    for (i = 1, s_offset = nbytes; i < nprocs; i++, s_offset = i * nbytes)
+      smpi_op_apply(op, (char *) recv + s_offset, tmp, &send_size, &dtype);
+
+    mpi_coll_allgather_fun(tmp, send_size, dtype, recv, send_size, dtype, comm);
+    memcpy(rbuff, recv, count * s_extent);
+
+    free(recv);
+    free(tmp);
+    free(send);
+  } else {
+    send = sbuff;
+    send_size = count / nprocs;
+    nbytes = send_size * s_extent;
+    r_offset = rank * nbytes;
+
+    recv = (void *) xbt_malloc(s_extent * send_size * nprocs);
+
+    mpi_coll_alltoall_fun(send, send_size, dtype, recv, send_size, dtype, comm);
+
+    memcpy((char *) rbuff + r_offset, recv, nbytes);
+
+    for (i = 1, s_offset = nbytes; i < nprocs; i++, s_offset = i * nbytes)
+      smpi_op_apply(op, (char *) recv + s_offset, (char *) rbuff + r_offset,
+                     &send_size, &dtype);
+
+    mpi_coll_allgather_fun((char *) rbuff + r_offset, send_size, dtype, rbuff, send_size,
+                  dtype, comm);
+    free(recv);
+  }
+
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-rdb.c b/src/smpi/colls/allreduce-rdb.c
new file mode 100644 (file)
index 0000000..44717ad
--- /dev/null
@@ -0,0 +1,124 @@
+#include "colls_private.h"
+//#include <star-reduction.c>
+
+int smpi_coll_tuned_allreduce_rdb(void *sbuff, void *rbuff, int count,
+                                  MPI_Datatype dtype, MPI_Op op, MPI_Comm comm)
+{
+  int nprocs, rank, tag = 543;
+  int mask, dst, pof2, newrank, rem, newdst;
+  MPI_Aint extent, lb;
+  MPI_Status status;
+  void *tmp_buf = NULL;
+  /*
+     #ifdef MPICH2_REDUCTION
+     MPI_User_function * uop = MPIR_Op_table[op % 16 - 1];
+     #else
+     MPI_User_function *uop;
+     struct MPIR_OP *op_ptr;
+     op_ptr = MPIR_ToPointer(op);
+     uop  = op_ptr->op;
+     #endif
+   */
+  nprocs=smpi_comm_size(comm);
+  rank=smpi_comm_rank(comm);
+
+  smpi_datatype_extent(dtype, &lb, &extent);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  smpi_mpi_sendrecv(sbuff, count, dtype, rank, 500,
+               rbuff, count, dtype, rank, 500, comm, &status);
+
+  // find nearest power-of-two less than or equal to comm_size
+  pof2 = 1;
+  while (pof2 <= nprocs)
+    pof2 <<= 1;
+  pof2 >>= 1;
+
+  rem = nprocs - pof2;
+
+  // In the non-power-of-two case, all even-numbered
+  // processes of rank < 2*rem send their data to
+  // (rank+1). These even-numbered processes no longer
+  // participate in the algorithm until the very end. The
+  // remaining processes form a nice power-of-two. 
+
+  if (rank < 2 * rem) {
+    // even       
+    if (rank % 2 == 0) {
+
+      smpi_mpi_send(rbuff, count, dtype, rank + 1, tag, comm);
+
+      // temporarily set the rank to -1 so that this
+      // process does not pariticipate in recursive
+      // doubling
+      newrank = -1;
+    } else                      // odd
+    {
+      smpi_mpi_recv(tmp_buf, count, dtype, rank - 1, tag, comm, &status);
+      // do the reduction on received data. since the
+      // ordering is right, it doesn't matter whether
+      // the operation is commutative or not.
+      smpi_op_apply(op, tmp_buf, rbuff, &count, &dtype);
+
+      // change the rank 
+      newrank = rank / 2;
+    }
+  }
+
+  else                          // rank >= 2 * rem 
+    newrank = rank - rem;
+
+  // If op is user-defined or count is less than pof2, use
+  // recursive doubling algorithm. Otherwise do a reduce-scatter
+  // followed by allgather. (If op is user-defined,
+  // derived datatypes are allowed and the user could pass basic
+  // datatypes on one process and derived on another as long as
+  // the type maps are the same. Breaking up derived
+  // datatypes to do the reduce-scatter is tricky, therefore
+  // using recursive doubling in that case.) 
+
+  if (newrank != -1) {
+    mask = 0x1;
+    while (mask < pof2) {
+      newdst = newrank ^ mask;
+      // find real rank of dest 
+      dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+
+      // Send the most current data, which is in recvbuf. Recv
+      // into tmp_buf 
+      smpi_mpi_sendrecv(rbuff, count, dtype, dst, tag, tmp_buf, count, dtype,
+                   dst, tag, comm, &status);
+
+      // tmp_buf contains data received in this step.
+      // recvbuf contains data accumulated so far 
+
+      // op is commutative OR the order is already right
+      // we assume it is commuttive op
+      //      if (op -> op_commute  || (dst < rank))
+      if ((dst < rank)) {
+        smpi_op_apply(op, tmp_buf, rbuff, &count, &dtype);
+      } else                    // op is noncommutative and the order is not right
+      {
+        smpi_op_apply(op, rbuff, tmp_buf, &count, &dtype);
+
+        // copy result back into recvbuf
+        smpi_mpi_sendrecv(tmp_buf, count, dtype, rank, tag, rbuff, count,
+                     dtype, rank, tag, comm, &status);
+      }
+      mask <<= 1;
+    }
+  }
+  // In the non-power-of-two case, all odd-numbered processes of
+  // rank < 2 * rem send the result to (rank-1), the ranks who didn't
+  // participate above.
+
+  if (rank < 2 * rem) {
+    if (rank % 2)               // odd 
+      smpi_mpi_send(rbuff, count, dtype, rank - 1, tag, comm);
+    else                        // even 
+      smpi_mpi_recv(rbuff, count, dtype, rank + 1, tag, comm, &status);
+  }
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-redbcast.c b/src/smpi/colls/allreduce-redbcast.c
new file mode 100644 (file)
index 0000000..69c552d
--- /dev/null
@@ -0,0 +1,10 @@
+#include "colls_private.h"
+
+int smpi_coll_tuned_allreduce_redbcast(void *buf, void *buf2, int count,
+                                       MPI_Datatype datatype, MPI_Op op,
+                                       MPI_Comm comm)
+{
+  smpi_mpi_reduce(buf, buf2, count, datatype, op, 0, comm);
+  smpi_mpi_bcast(buf2, count, datatype, 0, comm);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-smp-binomial-pipeline.c b/src/smpi/colls/allreduce-smp-binomial-pipeline.c
new file mode 100644 (file)
index 0000000..93d72bb
--- /dev/null
@@ -0,0 +1,194 @@
+#include "colls_private.h"
+/* IMPLEMENTED BY PITCH PATARASUK 
+   Non-topoloty-specific (however, number of cores/node need to be changed) 
+   all-reduce operation designed for smp clusters
+   It uses 2-layer communication: binomial for both intra-communication 
+   inter-communication
+   The communication are done in a pipeline fashion */
+
+/* change number of core per smp-node
+   we assume that number of core per process will be the same for all implementations */
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+/* this is a default segment size for pipelining, 
+   but it is typically passed as a command line argument */
+int allreduce_smp_binomial_pipeline_segment_size = 4096;
+
+/* ** NOTE **
+   This code is modified from allreduce-smp-binomial.c by wrapping the code with pipeline effect as follow
+   for (loop over pipelength) {
+     smp-binomial main code;
+   }
+*/
+
+/* ** NOTE **
+   Use -DMPICH2 if this code does not compile.
+   MPICH1 code also work on MPICH2 on our cluster and the performance are similar.
+   This code assume commutative and associative reduce operator (MPI_SUM, MPI_MAX, etc).
+*/
+
+/*
+This fucntion performs all-reduce operation as follow. ** in a pipeline fashion **
+1) binomial_tree reduce inside each SMP node
+2) binomial_tree reduce intra-communication between root of each SMP node
+3) binomial_tree bcast intra-communication between root of each SMP node
+4) binomial_tree bcast inside each SMP node
+*/
+int smpi_coll_tuned_allreduce_smp_binomial_pipeline(void *send_buf,
+                                                    void *recv_buf, int count,
+                                                    MPI_Datatype dtype,
+                                                    MPI_Op op, MPI_Comm comm)
+{
+  int comm_size, rank;
+  void *tmp_buf;
+  int tag = 50;
+  int mask, src, dst;
+  MPI_Status status;
+  int num_core = NUM_CORE;
+
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  int intra_rank, inter_rank;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+
+  int phase;
+  int send_offset;
+  int recv_offset;
+  int pcount = allreduce_smp_binomial_pipeline_segment_size;
+  if (pcount > count) {
+    pcount = count;
+  }
+
+  /* size of processes participate in intra communications =>
+     should be equal to number of machines */
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+
+  /* copy input buffer to output buffer */
+  smpi_mpi_sendrecv(send_buf, count, dtype, rank, tag,
+               recv_buf, count, dtype, rank, tag, comm, &status);
+
+  /* compute pipe length */
+  int pipelength;
+  pipelength = count / pcount;
+
+  /* pipelining over pipelength (+3 is because we have 4 stages:
+     reduce-intra, reduce-inter, bcast-inter, bcast-intra */
+  for (phase = 0; phase < pipelength + 3; phase++) {
+
+    /* start binomial reduce intra communication inside each SMP node */
+    if (phase < pipelength) {
+      mask = 1;
+      while (mask < num_core) {
+        if ((mask & intra_rank) == 0) {
+          src = (inter_rank * num_core) + (intra_rank | mask);
+          if (src < comm_size) {
+            recv_offset = phase * pcount * extent;
+            smpi_mpi_recv(tmp_buf, pcount, dtype, src, tag, comm, &status);
+            smpi_op_apply(op, tmp_buf, (char *)recv_buf + recv_offset, &pcount, &dtype);
+          }
+        } else {
+          send_offset = phase * pcount * extent;
+          dst = (inter_rank * num_core) + (intra_rank & (~mask));
+          smpi_mpi_send((char *)recv_buf + send_offset, pcount, dtype, dst, tag, comm);
+          break;
+        }
+        mask <<= 1;
+      }
+    }
+
+    /* start binomial reduce inter-communication between each SMP nodes: 
+       each node only have one process that can communicate to other nodes */
+    if ((phase > 0) && (phase < (pipelength + 1))) {
+      if (intra_rank == 0) {
+
+        mask = 1;
+        while (mask < inter_comm_size) {
+          if ((mask & inter_rank) == 0) {
+            src = (inter_rank | mask) * num_core;
+            if (src < comm_size) {
+              recv_offset = (phase - 1) * pcount * extent;
+              smpi_mpi_recv(tmp_buf, pcount, dtype, src, tag, comm, &status);
+              smpi_op_apply(op, tmp_buf, (char *)recv_buf + recv_offset, &pcount, &dtype);
+            }
+          } else {
+            dst = (inter_rank & (~mask)) * num_core;
+            send_offset = (phase - 1) * pcount * extent;
+            smpi_mpi_send((char *)recv_buf + send_offset, pcount, dtype, dst, tag, comm);
+            break;
+          }
+          mask <<= 1;
+        }
+      }
+    }
+
+    /* start binomial broadcast inter-communication between each SMP nodes: 
+       each node only have one process that can communicate to other nodes */
+    if ((phase > 1) && (phase < (pipelength + 2))) {
+      if (intra_rank == 0) {
+        mask = 1;
+        while (mask < inter_comm_size) {
+          if (inter_rank & mask) {
+            src = (inter_rank - mask) * num_core;
+            recv_offset = (phase - 2) * pcount * extent;
+            smpi_mpi_recv((char *)recv_buf + recv_offset, pcount, dtype, src, tag, comm,
+                     &status);
+            break;
+          }
+          mask <<= 1;
+        }
+        mask >>= 1;
+
+        while (mask > 0) {
+          if (inter_rank < inter_comm_size) {
+            dst = (inter_rank + mask) * num_core;
+            if (dst < comm_size) {
+              //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+              send_offset = (phase - 2) * pcount * extent;
+              smpi_mpi_send((char *)recv_buf + send_offset, pcount, dtype, dst, tag, comm);
+            }
+          }
+          mask >>= 1;
+        }
+      }
+    }
+
+    /* start binomial broadcast intra-communication inside each SMP nodes */
+    if (phase > 2) {
+      int num_core_in_current_smp = num_core;
+      if (inter_rank == (inter_comm_size - 1)) {
+        num_core_in_current_smp = comm_size - (inter_rank * num_core);
+      }
+      mask = 1;
+      while (mask < num_core_in_current_smp) {
+        if (intra_rank & mask) {
+          src = (inter_rank * num_core) + (intra_rank - mask);
+          recv_offset = (phase - 3) * pcount * extent;
+          smpi_mpi_recv((char *)recv_buf + recv_offset, pcount, dtype, src, tag, comm,
+                   &status);
+          break;
+        }
+        mask <<= 1;
+      }
+      mask >>= 1;
+
+      while (mask > 0) {
+        dst = (inter_rank * num_core) + (intra_rank + mask);
+        if (dst < comm_size) {
+          send_offset = (phase - 3) * pcount * extent;
+          smpi_mpi_send((char *)recv_buf + send_offset, pcount, dtype, dst, tag, comm);
+        }
+        mask >>= 1;
+      }
+    }
+  }                             // for phase
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-smp-binomial.c b/src/smpi/colls/allreduce-smp-binomial.c
new file mode 100644 (file)
index 0000000..ed9b68c
--- /dev/null
@@ -0,0 +1,147 @@
+#include "colls_private.h"
+/* IMPLEMENTED BY PITCH PATARASUK 
+   Non-topoloty-specific (however, number of cores/node need to be changed) 
+   all-reduce operation designed for smp clusters
+   It uses 2-layer communication: binomial for both intra-communication 
+   inter-communication*/
+
+/* change number of core per smp-node
+   we assume that number of core per process will be the same for all implementations */
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+/* ** NOTE **
+   Use -DMPICH2 if this code does not compile.
+   MPICH1 code also work on MPICH2 on our cluster and the performance are similar.
+   This code assume commutative and associative reduce operator (MPI_SUM, MPI_MAX, etc).
+*/
+
+//#include <star-reduction.c>
+
+/*
+This fucntion performs all-reduce operation as follow.
+1) binomial_tree reduce inside each SMP node
+2) binomial_tree reduce intra-communication between root of each SMP node
+3) binomial_tree bcast intra-communication between root of each SMP node
+4) binomial_tree bcast inside each SMP node
+*/
+int smpi_coll_tuned_allreduce_smp_binomial(void *send_buf, void *recv_buf,
+                                           int count, MPI_Datatype dtype,
+                                           MPI_Op op, MPI_Comm comm)
+{
+  int comm_size, rank;
+  void *tmp_buf;
+  int tag = 50;
+  int mask, src, dst;
+  int num_core = NUM_CORE;
+  MPI_Status status;
+
+  comm_size=smpi_comm_size(comm);
+  rank=smpi_comm_rank(comm);
+  MPI_Aint extent, lb;
+  smpi_datatype_extent(dtype, &lb, &extent);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  /* compute intra and inter ranking */
+  int intra_rank, inter_rank;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+
+  /* size of processes participate in intra communications =>
+     should be equal to number of machines */
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+
+  /* copy input buffer to output buffer */
+  smpi_mpi_sendrecv(send_buf, count, dtype, rank, tag,
+               recv_buf, count, dtype, rank, tag, comm, &status);
+
+  /* start binomial reduce intra communication inside each SMP node */
+  mask = 1;
+  while (mask < num_core) {
+    if ((mask & intra_rank) == 0) {
+      src = (inter_rank * num_core) + (intra_rank | mask);
+      if (src < comm_size) {
+        smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+      }
+    } else {
+      dst = (inter_rank * num_core) + (intra_rank & (~mask));
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+      break;
+    }
+    mask <<= 1;
+  }
+
+  /* start binomial reduce inter-communication between each SMP nodes: 
+     each node only have one process that can communicate to other nodes */
+  if (intra_rank == 0) {
+    mask = 1;
+    while (mask < inter_comm_size) {
+      if ((mask & inter_rank) == 0) {
+        src = (inter_rank | mask) * num_core;
+        if (src < comm_size) {
+          smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+          smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+        }
+      } else {
+        dst = (inter_rank & (~mask)) * num_core;
+        smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+        break;
+      }
+      mask <<= 1;
+    }
+  }
+
+  /* start binomial broadcast inter-communication between each SMP nodes: 
+     each node only have one process that can communicate to other nodes */
+  if (intra_rank == 0) {
+    mask = 1;
+    while (mask < inter_comm_size) {
+      if (inter_rank & mask) {
+        src = (inter_rank - mask) * num_core;
+        smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+        break;
+      }
+      mask <<= 1;
+    }
+    mask >>= 1;
+
+    while (mask > 0) {
+      if (inter_rank < inter_comm_size) {
+        dst = (inter_rank + mask) * num_core;
+        if (dst < comm_size) {
+          smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+        }
+      }
+      mask >>= 1;
+    }
+  }
+
+  /* start binomial broadcast intra-communication inside each SMP nodes */
+  int num_core_in_current_smp = num_core;
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * num_core);
+  }
+  mask = 1;
+  while (mask < num_core_in_current_smp) {
+    if (intra_rank & mask) {
+      src = (inter_rank * num_core) + (intra_rank - mask);
+      smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+      break;
+    }
+    mask <<= 1;
+  }
+  mask >>= 1;
+
+  while (mask > 0) {
+    dst = (inter_rank * num_core) + (intra_rank + mask);
+    if (dst < comm_size) {
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+    }
+    mask >>= 1;
+  }
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-smp-rdb.c b/src/smpi/colls/allreduce-smp-rdb.c
new file mode 100644 (file)
index 0000000..d208584
--- /dev/null
@@ -0,0 +1,180 @@
+#include "colls_private.h"
+/* IMPLEMENTED BY PITCH PATARASUK 
+   Non-topoloty-specific (however, number of cores/node need to be changed) 
+   all-reduce operation designed for smp clusters
+   It uses 2-layer communication: binomial for intra-communication 
+   and rdb for inter-communication*/
+
+/* change number of core per smp-node
+   we assume that number of core per process will be the same for all implementations */
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+/* ** NOTE **
+   Use -DMPICH2 if this code does not compile.
+   MPICH1 code also work on MPICH2 on our cluster and the performance are similar.
+   This code assume commutative and associative reduce operator (MPI_SUM, MPI_MAX, etc).
+*/
+
+//#include <star-reduction.c>
+
+/*
+This fucntion performs all-reduce operation as follow.
+1) binomial_tree reduce inside each SMP node
+2) Recursive doubling intra-communication between root of each SMP node
+3) binomial_tree bcast inside each SMP node
+*/
+int smpi_coll_tuned_allreduce_smp_rdb(void *send_buf, void *recv_buf, int count,
+                                      MPI_Datatype dtype, MPI_Op op,
+                                      MPI_Comm comm)
+{
+  int comm_size, rank;
+  void *tmp_buf;
+  int tag = 50;
+  int mask, src, dst;
+  MPI_Status status;
+  int num_core = NUM_CORE;
+  /*
+     #ifdef MPICH2_REDUCTION
+     MPI_User_function * uop = MPIR_Op_table[op % 16 - 1];
+     #else
+     MPI_User_function *uop;
+     struct MPIR_OP *op_ptr;
+     op_ptr = MPIR_ToPointer(op);
+     uop  = op_ptr->op;
+     #endif
+   */
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  /* compute intra and inter ranking */
+  int intra_rank, inter_rank;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+
+  /* size of processes participate in intra communications =>
+     should be equal to number of machines */
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+
+  /* copy input buffer to output buffer */
+  smpi_mpi_sendrecv(send_buf, count, dtype, rank, tag,
+               recv_buf, count, dtype, rank, tag, comm, &status);
+
+  /* start binomial reduce intra communication inside each SMP node */
+  mask = 1;
+  while (mask < num_core) {
+    if ((mask & intra_rank) == 0) {
+      src = (inter_rank * num_core) + (intra_rank | mask);
+      if (src < comm_size) {
+        smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+      }
+    } else {
+      dst = (inter_rank * num_core) + (intra_rank & (~mask));
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+      break;
+    }
+    mask <<= 1;
+  }                             /* end binomial reduce intra-communication */
+
+
+  /* start rdb (recursive doubling) all-reduce inter-communication 
+     between each SMP nodes : each node only have one process that can communicate
+     to other nodes */
+  if (intra_rank == 0) {
+
+    /* find nearest power-of-two less than or equal to inter_comm_size */
+    int pof2, rem, newrank, newdst;
+    pof2 = 1;
+    while (pof2 <= inter_comm_size)
+      pof2 <<= 1;
+    pof2 >>= 1;
+    rem = inter_comm_size - pof2;
+
+    /* In the non-power-of-two case, all even-numbered
+       processes of rank < 2*rem send their data to
+       (rank+1). These even-numbered processes no longer
+       participate in the algorithm until the very end.
+     */
+    if (inter_rank < 2 * rem) {
+      if (inter_rank % 2 == 0) {
+        dst = rank + num_core;
+        smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+        newrank = -1;
+      } else {
+        src = rank - num_core;
+        smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+        newrank = inter_rank / 2;
+      }
+    } else {
+      newrank = inter_rank - rem;
+    }
+
+    /* example inter-communication RDB rank change algorithm 
+       0,4,8,12..36 <= true rank (assume 4 core per SMP)
+       0123 4567 89 <= inter_rank
+       1 3 4567 89 (1,3 got data from 0,2 : 0,2 will be idle until the end)
+       0 1 4567 89 
+       0 1 2345 67 => newrank
+     */
+
+    if (newrank != -1) {
+      mask = 1;
+      while (mask < pof2) {
+        newdst = newrank ^ mask;
+        /* find real rank of dest */
+        dst = (newdst < rem) ? newdst * 2 + 1 : newdst + rem;
+        dst *= num_core;
+
+        /* exchange data in rdb manner */
+        smpi_mpi_sendrecv(recv_buf, count, dtype, dst, tag, tmp_buf, count, dtype,
+                     dst, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+        mask <<= 1;
+      }
+    }
+
+    /* non pof2 case 
+       left-over processes (all even ranks: < 2 * rem) get the result    
+     */
+    if (inter_rank < 2 * rem) {
+      if (inter_rank % 2) {
+        smpi_mpi_send(recv_buf, count, dtype, rank - num_core, tag, comm);
+      } else {
+        smpi_mpi_recv(recv_buf, count, dtype, rank + num_core, tag, comm, &status);
+      }
+    }
+  }
+
+  /* start binomial broadcast intra-communication inside each SMP nodes */
+  int num_core_in_current_smp = num_core;
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * num_core);
+  }
+  mask = 1;
+  while (mask < num_core_in_current_smp) {
+    if (intra_rank & mask) {
+      src = (inter_rank * num_core) + (intra_rank - mask);
+      smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+      break;
+    }
+    mask <<= 1;
+  }
+  mask >>= 1;
+
+  while (mask > 0) {
+    dst = (inter_rank * num_core) + (intra_rank + mask);
+    if (dst < comm_size) {
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+    }
+    mask >>= 1;
+  }
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-smp-rsag-lr.c b/src/smpi/colls/allreduce-smp-rsag-lr.c
new file mode 100644 (file)
index 0000000..fd49327
--- /dev/null
@@ -0,0 +1,254 @@
+#include "colls_private.h"
+//#include <star-reduction.c>
+
+/* change number of core per smp-node
+   we assume that number of core per process will be the same for all implementations */
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+/*
+This fucntion performs all-reduce operation as follow.
+1) binomial_tree reduce inside each SMP node
+2) reduce-scatter -inter between root of each SMP node
+3) allgather - inter between root of each SMP node
+4) binomial_tree bcast inside each SMP node
+*/
+int smpi_coll_tuned_allreduce_smp_rsag_lr(void *send_buf, void *recv_buf,
+                                          int count, MPI_Datatype dtype,
+                                          MPI_Op op, MPI_Comm comm)
+{
+  int comm_size, rank;
+  void *tmp_buf;
+  int tag = 50;
+  int mask, src, dst;
+  MPI_Status status;
+  int num_core = NUM_CORE;
+  /*
+     #ifdef MPICH2_REDUCTION
+     MPI_User_function * uop = MPIR_Op_table[op % 16 - 1];
+     #else
+     MPI_User_function *uop;
+     struct MPIR_OP *op_ptr;
+     op_ptr = MPIR_ToPointer(op);
+     uop  = op_ptr->op;
+     #endif
+   */
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  int intra_rank, inter_rank;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+
+  //printf("node %d intra_rank = %d, inter_rank = %d\n", rank, intra_rank, inter_rank);
+
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+
+  if (!rank) {
+    //printf("intra com size = %d\n",num_core);
+    //printf("inter com size = %d\n",inter_comm_size);
+  }
+
+
+  smpi_mpi_sendrecv(send_buf, count, dtype, rank, tag,
+               recv_buf, count, dtype, rank, tag, comm, &status);
+
+
+  // SMP_binomial_reduce
+  mask = 1;
+  while (mask < num_core) {
+    if ((mask & intra_rank) == 0) {
+      src = (inter_rank * num_core) + (intra_rank | mask);
+      //      if (src < ((inter_rank + 1) * num_core)) {
+      if (src < comm_size) {
+        smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+        //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+      }
+    } else {
+
+      dst = (inter_rank * num_core) + (intra_rank & (~mask));
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+      //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+      break;
+    }
+    mask <<= 1;
+  }
+
+
+
+  // INTER: reduce-scatter
+  if (intra_rank == 0) {
+    int send_offset, recv_offset;
+    int send_count, recv_count;
+    int curr_size = count / inter_comm_size;
+    int curr_remainder = count % inter_comm_size;
+
+    int to = ((inter_rank + 1) % inter_comm_size) * num_core;
+    int from =
+        ((inter_rank + inter_comm_size - 1) % inter_comm_size) * num_core;
+    int i;
+
+    //printf("node %d to %d from %d\n",rank,to,from);
+
+    /* last segment may have a larger size since it also include the remainder */
+    int last_segment_ptr =
+        (inter_comm_size - 1) * (count / inter_comm_size) * extent;
+
+    for (i = 0; i < (inter_comm_size - 1); i++) {
+
+      send_offset =
+          ((inter_rank - 1 - i +
+            inter_comm_size) % inter_comm_size) * curr_size * extent;
+      recv_offset =
+          ((inter_rank - 2 - i +
+            inter_comm_size) % inter_comm_size) * curr_size * extent;
+
+      /* adjust size */
+      if (send_offset != last_segment_ptr)
+        send_count = curr_size;
+      else
+        send_count = curr_size + curr_remainder;
+
+      if (recv_offset != last_segment_ptr)
+        recv_count = curr_size;
+      else
+        recv_count = curr_size + curr_remainder;
+
+      smpi_mpi_sendrecv((char *) recv_buf + send_offset, send_count, dtype, to,
+                   tag + i, tmp_buf, recv_count, dtype, from, tag + i, comm,
+                   &status);
+
+      // result is in rbuf
+      smpi_op_apply(op, tmp_buf, (char *) recv_buf + recv_offset, &recv_count,
+                     &dtype);
+    }
+
+    // INTER: allgather
+    for (i = 0; i < (inter_comm_size - 1); i++) {
+
+      send_offset =
+          ((inter_rank - i +
+            inter_comm_size) % inter_comm_size) * curr_size * extent;
+      recv_offset =
+          ((inter_rank - 1 - i +
+            inter_comm_size) % inter_comm_size) * curr_size * extent;
+
+      /* adjust size */
+      if (send_offset != last_segment_ptr)
+        send_count = curr_size;
+      else
+        send_count = curr_size + curr_remainder;
+
+      if (recv_offset != last_segment_ptr)
+        recv_count = curr_size;
+      else
+        recv_count = curr_size + curr_remainder;
+
+      smpi_mpi_sendrecv((char *) recv_buf + send_offset, send_count, dtype, to,
+                   tag + i, (char *) recv_buf + recv_offset, recv_count, dtype,
+                   from, tag + i, comm, &status);
+
+    }
+  }
+
+
+
+  /*
+     // INTER_binomial_reduce
+
+     // only root node for each SMP
+     if (intra_rank == 0) {
+
+     mask = 1;
+     while (mask < inter_comm_size) {
+     if ((mask & inter_rank) == 0) {
+     src = (inter_rank | mask) * num_core;
+     if (src < comm_size) {
+     smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+     (* uop) (tmp_buf, recv_buf, &count, &dtype);
+     //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+     }
+     }
+     else {
+     dst = (inter_rank & (~mask)) * num_core;
+     smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+     //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+     break;
+     }
+     mask <<=1;
+     }
+     }
+   */
+
+  /*
+     // INTER_binomial_bcast
+
+
+     if (intra_rank == 0) {
+     mask = 1;
+     while (mask < inter_comm_size) {
+     if (inter_rank & mask) {
+     src = (inter_rank - mask) * num_core;
+     //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+     smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+     break;
+     }
+     mask <<= 1;
+     }
+
+     mask >>= 1;
+     //printf("My rank = %d my mask = %d\n", rank,mask);
+
+     while (mask > 0) {
+     if (inter_rank < inter_comm_size) {
+     dst = (inter_rank + mask) * num_core;
+     if (dst < comm_size) {
+     //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+     smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+     }
+     }
+     mask >>= 1;
+     }
+     }
+   */
+
+
+  // INTRA_binomial_bcast
+
+  int num_core_in_current_smp = num_core;
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * num_core);
+  }
+  //  printf("Node %d num_core = %d\n",rank, num_core_in_current_smp);
+  mask = 1;
+  while (mask < num_core_in_current_smp) {
+    if (intra_rank & mask) {
+      src = (inter_rank * num_core) + (intra_rank - mask);
+      //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+      smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+      break;
+    }
+    mask <<= 1;
+  }
+
+  mask >>= 1;
+  //printf("My rank = %d my mask = %d\n", rank,mask);
+
+  while (mask > 0) {
+    dst = (inter_rank * num_core) + (intra_rank + mask);
+    if (dst < comm_size) {
+      //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+    }
+    mask >>= 1;
+  }
+
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-smp-rsag-rab.c b/src/smpi/colls/allreduce-smp-rsag-rab.c
new file mode 100644 (file)
index 0000000..c98b78d
--- /dev/null
@@ -0,0 +1,205 @@
+#include "colls_private.h"
+/* 
+ * implemented by Pitch Patarasuk, 07/01/2007
+ */
+//#include <star-reduction.c>
+
+/* change number of core per smp-node
+   we assume that number of core per process will be the same for all implementations */
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+/*
+This fucntion performs all-reduce operation as follow.
+1) binomial_tree reduce inside each SMP node
+2) reduce-scatter -inter between root of each SMP node
+3) allgather - inter between root of each SMP node
+4) binomial_tree bcast inside each SMP node
+*/
+int smpi_coll_tuned_allreduce_smp_rsag_rab(void *sbuf, void *rbuf, int count,
+                                           MPI_Datatype dtype, MPI_Op op,
+                                           MPI_Comm comm)
+{
+  int comm_size, rank;
+  void *tmp_buf;
+  int tag = 50;
+  int mask, src, dst;
+  MPI_Status status;
+  int num_core = NUM_CORE;
+
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  int intra_rank, inter_rank;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+
+  //printf("node %d intra_rank = %d, inter_rank = %d\n", rank, intra_rank, inter_rank);
+
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+
+  smpi_mpi_sendrecv(sbuf, count, dtype, rank, tag,
+               rbuf, count, dtype, rank, tag, comm, &status);
+
+  // SMP_binomial_reduce
+  mask = 1;
+  while (mask < num_core) {
+    if ((mask & intra_rank) == 0) {
+      src = (inter_rank * num_core) + (intra_rank | mask);
+      //      if (src < ((inter_rank + 1) * num_core)) {
+      if (src < comm_size) {
+        smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, rbuf, &count, &dtype);
+        //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+      }
+    } else {
+
+      dst = (inter_rank * num_core) + (intra_rank & (~mask));
+      smpi_mpi_send(rbuf, count, dtype, dst, tag, comm);
+      //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+      break;
+    }
+    mask <<= 1;
+  }
+
+
+  // INTER: reduce-scatter
+  if (intra_rank == 0) {
+
+    int dst, base_offset, send_base_offset, recv_base_offset, recv_chunk;
+    int curr_count, i, recv_offset, send_offset;
+
+    // reduce-scatter
+
+    recv_chunk = extent * count / (comm_size / num_core);
+
+    mask = 1;
+    i = 0;
+    curr_count = count / 2;
+    int phase = 0;
+    base_offset = 0;
+    send_base_offset = 0;
+    recv_base_offset = 0;
+
+    while (mask < (comm_size / num_core)) {
+      dst = inter_rank ^ mask;
+
+      // compute offsets
+      send_base_offset = base_offset;
+
+      // right-handside
+      if (inter_rank & mask) {
+        recv_base_offset = base_offset + curr_count;
+        send_base_offset = base_offset;
+        base_offset = recv_base_offset;
+      }
+      // left-handside
+      else {
+        recv_base_offset = base_offset;
+        send_base_offset = base_offset + curr_count;
+      }
+      send_offset = send_base_offset * extent;
+      recv_offset = recv_base_offset * extent;
+
+      //      if (rank==7)
+      //      printf("node %d send to %d in phase %d s_offset = %d r_offset = %d count = %d\n",rank,dst,phase, send_offset, recv_offset, curr_count);
+
+      smpi_mpi_sendrecv((char *)rbuf + send_offset, curr_count, dtype, (dst * num_core), tag,
+                   tmp_buf, curr_count, dtype, (dst * num_core), tag,
+                   comm, &status);
+
+      smpi_op_apply(op, tmp_buf, (char *)rbuf + recv_offset, &curr_count, &dtype);
+
+      mask *= 2;
+      curr_count /= 2;
+      phase++;
+    }
+
+
+    // INTER: allgather
+
+    int size = (comm_size / num_core) / 2;
+    base_offset = 0;
+    mask = 1;
+    while (mask < (comm_size / num_core)) {
+      if (inter_rank & mask) {
+        base_offset += size;
+      }
+      mask <<= 1;
+      size /= 2;
+    }
+
+    curr_count *= 2;
+    mask >>= 1;
+    i = 1;
+    phase = 0;
+    while (mask >= 1) {
+      // destination pair for both send and recv
+      dst = inter_rank ^ mask;
+
+      // compute offsets
+      send_base_offset = base_offset;
+      if (inter_rank & mask) {
+        recv_base_offset = base_offset - i;
+        base_offset -= i;
+      } else {
+        recv_base_offset = base_offset + i;
+      }
+      send_offset = send_base_offset * recv_chunk;
+      recv_offset = recv_base_offset * recv_chunk;
+
+      //      if (rank==7)
+      //printf("node %d send to %d in phase %d s_offset = %d r_offset = %d count = %d\n",rank,dst,phase, send_offset, recv_offset, curr_count);
+
+      smpi_mpi_sendrecv((char *)rbuf + send_offset, curr_count, dtype, (dst * num_core), tag,
+                   (char *)rbuf + recv_offset, curr_count, dtype, (dst * num_core), tag,
+                   comm, &status);
+
+
+      curr_count *= 2;
+      i *= 2;
+      mask >>= 1;
+      phase++;
+    }
+
+
+  }                             // INTER
+
+  // intra SMP binomial bcast
+
+  int num_core_in_current_smp = num_core;
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * num_core);
+  }
+  //  printf("Node %d num_core = %d\n",rank, num_core_in_current_smp);
+  mask = 1;
+  while (mask < num_core_in_current_smp) {
+    if (intra_rank & mask) {
+      src = (inter_rank * num_core) + (intra_rank - mask);
+      //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+      smpi_mpi_recv(rbuf, count, dtype, src, tag, comm, &status);
+      break;
+    }
+    mask <<= 1;
+  }
+
+  mask >>= 1;
+  //printf("My rank = %d my mask = %d\n", rank,mask);
+
+  while (mask > 0) {
+    dst = (inter_rank * num_core) + (intra_rank + mask);
+    if (dst < comm_size) {
+      //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+      smpi_mpi_send(rbuf, count, dtype, dst, tag, comm);
+    }
+    mask >>= 1;
+  }
+
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
diff --git a/src/smpi/colls/allreduce-smp-rsag.c b/src/smpi/colls/allreduce-smp-rsag.c
new file mode 100644 (file)
index 0000000..24ccaa0
--- /dev/null
@@ -0,0 +1,224 @@
+#include "colls_private.h"
+
+/* change number of core per smp-node
+   we assume that number of core per process will be the same for all implementations */
+#ifndef NUM_CORE
+#define NUM_CORE 8
+#endif
+
+/*
+This fucntion performs all-reduce operation as follow.
+1) binomial_tree reduce inside each SMP node
+2) reduce-scatter -inter between root of each SMP node
+3) allgather - inter between root of each SMP node
+4) binomial_tree bcast inside each SMP node
+*/
+int smpi_coll_tuned_allreduce_smp_rsag(void *send_buf, void *recv_buf,
+                                       int count, MPI_Datatype dtype, MPI_Op op,
+                                       MPI_Comm comm)
+{
+  int comm_size, rank;
+  void *tmp_buf;
+  int tag = 50;
+  int mask, src, dst;
+  MPI_Status status;
+  int num_core = NUM_CORE;
+  /*
+     #ifdef MPICH2_REDUCTION
+     MPI_User_function * uop = MPIR_Op_table[op % 16 - 1];
+     #else
+     MPI_User_function *uop;
+     struct MPIR_OP *op_ptr;
+     op_ptr = MPIR_ToPointer(op);
+     uop  = op_ptr->op;
+     #endif
+   */
+  comm_size = smpi_comm_size(comm);
+  rank = smpi_comm_rank(comm);
+  MPI_Aint extent;
+  extent = smpi_datatype_get_extent(dtype);
+  tmp_buf = (void *) xbt_malloc(count * extent);
+
+  int intra_rank, inter_rank;
+  intra_rank = rank % num_core;
+  inter_rank = rank / num_core;
+
+  //printf("node %d intra_rank = %d, inter_rank = %d\n", rank, intra_rank, inter_rank);
+
+  int inter_comm_size = (comm_size + num_core - 1) / num_core;
+
+  if (!rank) {
+    //printf("intra com size = %d\n",num_core);
+    //printf("inter com size = %d\n",inter_comm_size);
+  }
+
+
+  smpi_mpi_sendrecv(send_buf, count, dtype, rank, tag,
+               recv_buf, count, dtype, rank, tag, comm, &status);
+
+
+  // SMP_binomial_reduce
+  mask = 1;
+  while (mask < num_core) {
+    if ((mask & intra_rank) == 0) {
+      src = (inter_rank * num_core) + (intra_rank | mask);
+      //      if (src < ((inter_rank + 1) * num_core)) {
+      if (src < comm_size) {
+        smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+        smpi_op_apply(op, tmp_buf, recv_buf, &count, &dtype);
+        //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+      }
+    } else {
+
+      dst = (inter_rank * num_core) + (intra_rank & (~mask));
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+      //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+      break;
+    }
+    mask <<= 1;
+  }
+
+
+
+  // INTER: reduce-scatter
+  if (intra_rank == 0) {
+    int send_offset, recv_offset;
+    int seg_count = count / inter_comm_size;
+    int to = ((inter_rank + 1) % inter_comm_size) * num_core;
+    int from =
+        ((inter_rank + inter_comm_size - 1) % inter_comm_size) * num_core;
+    int i;
+
+    //printf("node %d to %d from %d\n",rank,to,from);
+
+    for (i = 0; i < (inter_comm_size - 1); i++) {
+
+      send_offset =
+          ((inter_rank - 1 - i +
+            inter_comm_size) % inter_comm_size) * seg_count * extent;
+      recv_offset =
+          ((inter_rank - 2 - i +
+            inter_comm_size) % inter_comm_size) * seg_count * extent;
+
+      smpi_mpi_sendrecv((char *) recv_buf + send_offset, seg_count, dtype, to,
+                   tag + i, tmp_buf, seg_count, dtype, from, tag + i, comm,
+                   &status);
+
+      // result is in rbuf
+      smpi_op_apply(op, tmp_buf, (char *) recv_buf + recv_offset, &seg_count,
+                     &dtype);
+    }
+
+    // INTER: allgather
+    for (i = 0; i < (inter_comm_size - 1); i++) {
+
+      send_offset =
+          ((inter_rank - i +
+            inter_comm_size) % inter_comm_size) * seg_count * extent;
+      recv_offset =
+          ((inter_rank - 1 - i +
+            inter_comm_size) % inter_comm_size) * seg_count * extent;
+
+      smpi_mpi_sendrecv((char *) recv_buf + send_offset, seg_count, dtype, to,
+                   tag + i, (char *) recv_buf + recv_offset, seg_count, dtype,
+                   from, tag + i, comm, &status);
+
+    }
+  }
+
+
+
+  /*
+     // INTER_binomial_reduce
+
+     // only root node for each SMP
+     if (intra_rank == 0) {
+
+     mask = 1;
+     while (mask < inter_comm_size) {
+     if ((mask & inter_rank) == 0) {
+     src = (inter_rank | mask) * num_core;
+     if (src < comm_size) {
+     smpi_mpi_recv(tmp_buf, count, dtype, src, tag, comm, &status);
+     (* uop) (tmp_buf, recv_buf, &count, &dtype);
+     //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+     }
+     }
+     else {
+     dst = (inter_rank & (~mask)) * num_core;
+     smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+     //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+     break;
+     }
+     mask <<=1;
+     }
+     }
+   */
+
+  /*
+     // INTER_binomial_bcast
+
+
+     if (intra_rank == 0) {
+     mask = 1;
+     while (mask < inter_comm_size) {
+     if (inter_rank & mask) {
+     src = (inter_rank - mask) * num_core;
+     //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+     smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+     break;
+     }
+     mask <<= 1;
+     }
+
+     mask >>= 1;
+     //printf("My rank = %d my mask = %d\n", rank,mask);
+
+     while (mask > 0) {
+     if (inter_rank < inter_comm_size) {
+     dst = (inter_rank + mask) * num_core;
+     if (dst < comm_size) {
+     //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+     smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+     }
+     }
+     mask >>= 1;
+     }
+     }
+   */
+
+
+  // INTRA_binomial_bcast
+
+  int num_core_in_current_smp = num_core;
+  if (inter_rank == (inter_comm_size - 1)) {
+    num_core_in_current_smp = comm_size - (inter_rank * num_core);
+  }
+  //  printf("Node %d num_core = %d\n",rank, num_core_in_current_smp);
+  mask = 1;
+  while (mask < num_core_in_current_smp) {
+    if (intra_rank & mask) {
+      src = (inter_rank * num_core) + (intra_rank - mask);
+      //printf("Node %d recv from node %d when mask is %d\n", rank, src, mask);
+      smpi_mpi_recv(recv_buf, count, dtype, src, tag, comm, &status);
+      break;
+    }
+    mask <<= 1;
+  }
+
+  mask >>= 1;
+  //printf("My rank = %d my mask = %d\n", rank,mask);
+
+  while (mask > 0) {
+    dst = (inter_rank * num_core) + (intra_rank + mask);
+    if (dst < comm_size) {
+      //printf("Node %d send to node %d when mask is %d\n", rank, dst, mask);
+      smpi_mpi_send(recv_buf, count, dtype, dst, tag, comm);
+    }
+    mask >>= 1;
+  }
+
+
+  free(tmp_buf);
+  return MPI_SUCCESS;
+}
index 1e1e408..61ea21e 100644 (file)
@@ -1,7 +1,5 @@
-#include "colls.h"
+#include "colls_private.h"
 #include <math.h>
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_colls, smpi,
-                                "Logging specific to SMPI collectives");
 
 /*****************************************************************************
 
@@ -26,179 +24,147 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_colls, smpi,
  * Auther: Ahmad Faraj
 
 ****************************************************************************/
-int alltoall_check_is_2dmesh(int num, int * i, int * j)
+static int alltoall_check_is_2dmesh(int num, int *i, int *j)
 {
   int x, max = num / 2;
-  x = sqrt(num);  
-
-  while (x <= max)
-    {
-      if ((num % x) == 0)
-       {
-         * i = x;
-         * j = num / x;
-       
-         if (* i > * j)
-           {
-             x = * i;
-             * i = * j;
-             * j = x;
-           }
-       
-         return 1;
-       }
-      x++;
+  x = sqrt(num);
+
+  while (x <= max) {
+    if ((num % x) == 0) {
+      *i = x;
+      *j = num / x;
+
+      if (*i > *j) {
+        x = *i;
+        *i = *j;
+        *j = x;
+      }
+
+      return 1;
     }
+    x++;
+  }
   return 0;
 }
 
-int
-smpi_coll_tuned_alltoall_2dmesh(void * send_buff, int send_count, MPI_Datatype send_type,
-                     void * recv_buff, int recv_count, MPI_Datatype recv_type,
-                     MPI_Comm comm)
+int smpi_coll_tuned_alltoall_2dmesh(void *send_buff, int send_count,
+                                    MPI_Datatype send_type,
+                                    void *recv_buff, int recv_count,
+                                    MPI_Datatype recv_type, MPI_Comm comm)
 {
-  MPI_Status * statuses, s;
-  MPI_Request * reqs, * req_ptr;;
+  MPI_Status *statuses, s;
+  MPI_Request *reqs, *req_ptr;;
   MPI_Aint extent;
 
-  char * tmp_buff1, * tmp_buff2;
+  char *tmp_buff1, *tmp_buff2;
   int i, j, src, dst, rank, num_procs, count, num_reqs;
-  int rows, cols, my_row, my_col, X, Y, send_offset, recv_offset;
-  int two_dsize, my_row_base, my_col_base, src_row_base, block_size;
-  int tag = 1, failure = 0, success = 1;
-  
-  MPI_Comm_rank(comm, &rank);
-  MPI_Comm_size(comm, &num_procs);
-  MPI_Type_extent(send_type, &extent);
+  int X, Y, send_offset, recv_offset;
+  int my_row_base, my_col_base, src_row_base, block_size;
+  int tag = 1;
 
-  if (!alltoall_check_is_2dmesh(num_procs, &X, &Y))
-    return failure;
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
 
-  two_dsize = X * Y;
+  if (!alltoall_check_is_2dmesh(num_procs, &X, &Y))
+    return MPI_ERR_OTHER;
 
   my_row_base = (rank / Y) * Y;
   my_col_base = rank % Y;
 
   block_size = extent * send_count;
-  
-  tmp_buff1 =(char *) malloc(block_size * num_procs * Y);
-  if (!tmp_buff1)
-    {
-      XBT_DEBUG("alltoall-2dmesh_shoot.c:88: cannot allocate memory");
-      MPI_Finalize();
-      exit(failure);
-    }  
-
-  tmp_buff2 =(char *) malloc(block_size *  Y);  
-  if (!tmp_buff2)
-    {
-      XBT_WARN("alltoall-2dmesh_shoot.c:88: cannot allocate memory");
-      MPI_Finalize();
-      exit(failure);
-    }
-  
 
+  tmp_buff1 = (char *) xbt_malloc(block_size * num_procs * Y);
+  tmp_buff2 = (char *) xbt_malloc(block_size * Y);
 
   num_reqs = X;
-  if (Y > X) num_reqs = Y;
-
-  statuses = (MPI_Status *) malloc(num_reqs * sizeof(MPI_Status));  
-  reqs = (MPI_Request *) malloc(num_reqs * sizeof(MPI_Request));  
-  if (!reqs)
-    {
-      XBT_WARN("alltoall-2dmesh_shoot.c:88: cannot allocate memory");
-      MPI_Finalize();
-      exit(failure);
-    }
-  
+  if (Y > X)
+    num_reqs = Y;
+
+  statuses = (MPI_Status *) xbt_malloc(num_reqs * sizeof(MPI_Status));
+  reqs = (MPI_Request *) xbt_malloc(num_reqs * sizeof(MPI_Request));
+
   req_ptr = reqs;
 
   send_offset = recv_offset = (rank % Y) * block_size * num_procs;
 
   count = send_count * num_procs;
-  
-  for (i = 0; i < Y; i++)
-    {
-      src = i + my_row_base;
-      if (src == rank)
-       continue;
-
-      recv_offset = (src % Y) * block_size * num_procs;
-       MPI_Irecv(tmp_buff1 + recv_offset, count, recv_type, src, tag, comm,
-                req_ptr++);
-    }
-  
-  for (i = 0; i < Y; i++)
-    {
-      dst = i + my_row_base;
-      if (dst == rank)
-       continue;
-       MPI_Send(send_buff, count, send_type, dst, tag, comm);
-    }
-  
-  MPI_Waitall(Y - 1, reqs, statuses);
+
+  for (i = 0; i < Y; i++) {
+    src = i + my_row_base;
+    if (src == rank)
+      continue;
+
+    recv_offset = (src % Y) * block_size * num_procs;
+    *(req_ptr++) = smpi_mpi_irecv(tmp_buff1 + recv_offset, count, recv_type, src, tag, comm);
+  }
+
+  for (i = 0; i < Y; i++) {
+    dst = i + my_row_base;
+    if (dst == rank)
+      continue;
+    smpi_mpi_send(send_buff, count, send_type, dst, tag, comm);
+  }
+
+  smpi_mpi_waitall(Y - 1, reqs, statuses);
   req_ptr = reqs;
-  
-  for (i = 0; i < Y; i++)
-    {
-      send_offset = (rank * block_size) + (i * block_size * num_procs);
-      recv_offset = (my_row_base * block_size) + (i * block_size);
-     
-      if (i + my_row_base == rank) 
-       MPI_Sendrecv (send_buff + recv_offset, send_count, send_type,
-                     rank, tag, recv_buff + recv_offset, recv_count,
-                     recv_type, rank, tag, comm, &s);
-
-     else 
-         MPI_Sendrecv (tmp_buff1 + send_offset, send_count, send_type,
-                      rank, tag, 
-                      recv_buff + recv_offset, recv_count, recv_type,
-                      rank, tag, comm, &s);
-    }
 
-  
-  for (i = 0; i < X; i++)
-  {
-     src = (i * Y + my_col_base);
-     if (src == rank)
-       continue;
-     src_row_base = (src / Y) * Y;
+  for (i = 0; i < Y; i++) {
+    send_offset = (rank * block_size) + (i * block_size * num_procs);
+    recv_offset = (my_row_base * block_size) + (i * block_size);
+
+    if (i + my_row_base == rank)
+      smpi_mpi_sendrecv((char *) send_buff + recv_offset, send_count, send_type,
+                   rank, tag,
+                   (char *) recv_buff + recv_offset, recv_count, recv_type,
+                   rank, tag, comm, &s);
+
+    else
+      smpi_mpi_sendrecv(tmp_buff1 + send_offset, send_count, send_type,
+                   rank, tag,
+                   (char *) recv_buff + recv_offset, recv_count, recv_type,
+                   rank, tag, comm, &s);
+  }
+
+
+  for (i = 0; i < X; i++) {
+    src = (i * Y + my_col_base);
+    if (src == rank)
+      continue;
+    src_row_base = (src / Y) * Y;
 
-      MPI_Irecv(recv_buff + src_row_base * block_size, recv_count * Y,
-               recv_type, src, tag, comm, req_ptr++);
+    *(req_ptr++) = smpi_mpi_irecv((char *) recv_buff + src_row_base * block_size, recv_count * Y,
+              recv_type, src, tag, comm);
   }
-  
-  for (i = 0; i < X; i++)
-    {
-      dst = (i * Y + my_col_base);
-      if (dst == rank)
-       continue;
-
-      recv_offset = 0;
-      for (j = 0; j < Y; j++)
-       {
-         send_offset = (dst + j * num_procs) * block_size;
-
-         if (j + my_row_base == rank) 
-            MPI_Sendrecv (send_buff + dst * block_size, send_count, send_type,
-                          rank, tag, 
-                          tmp_buff2 + recv_offset, recv_count, recv_type,
-                          rank, tag, comm, &s);
-         else
-            MPI_Sendrecv (tmp_buff1 + send_offset, send_count, send_type,
-                          rank, tag, 
-                          tmp_buff2 + recv_offset, recv_count, recv_type,
-                          rank, tag, comm, &s);
-         
-         recv_offset += block_size;
-       }
-
-       MPI_Send(tmp_buff2, send_count * Y, send_type, dst, tag, comm);
+
+  for (i = 0; i < X; i++) {
+    dst = (i * Y + my_col_base);
+    if (dst == rank)
+      continue;
+
+    recv_offset = 0;
+    for (j = 0; j < Y; j++) {
+      send_offset = (dst + j * num_procs) * block_size;
+
+      if (j + my_row_base == rank)
+        smpi_mpi_sendrecv((char *) send_buff + dst * block_size, send_count,
+                     send_type, rank, tag, tmp_buff2 + recv_offset, recv_count,
+                     recv_type, rank, tag, comm, &s);
+      else
+        smpi_mpi_sendrecv(tmp_buff1 + send_offset, send_count, send_type,
+                     rank, tag,
+                     tmp_buff2 + recv_offset, recv_count, recv_type,
+                     rank, tag, comm, &s);
+
+      recv_offset += block_size;
     }
-  MPI_Waitall(X - 1, reqs, statuses);
+
+    smpi_mpi_send(tmp_buff2, send_count * Y, send_type, dst, tag, comm);
+  }
+  smpi_mpi_waitall(X - 1, reqs, statuses);
   free(reqs);
   free(statuses);
   free(tmp_buff1);
-  free(tmp_buff2);  
-  return success;
+  free(tmp_buff2);
+  return MPI_SUCCESS;
 }
index afd47ce..ca10de7 100644 (file)
@@ -1,4 +1,4 @@
-#include "colls.h"
+#include "colls_private.h"
 #include <math.h>
 
 /*****************************************************************************
  * Auther: Ahmad Faraj
 ****************************************************************************/
 
-int alltoall_check_is_3dmesh(int num, int * i, int * j, int * k)
+static int alltoall_check_is_3dmesh(int num, int *i, int *j, int *k)
 {
   int x, max = num / 3;
-  x = cbrt(num);  
-  * i = * j = * k = 0;
-  while (x <= max)
-    {
-      if ((num % (x * x)) == 0)
-       {
-         * i = * j = x;
-         * k = num / (x * x);
-         return 1;
-       }
-      x++;
+  x = cbrt(num);
+  *i = *j = *k = 0;
+  while (x <= max) {
+    if ((num % (x * x)) == 0) {
+      *i = *j = x;
+      *k = num / (x * x);
+      return 1;
     }
+    x++;
+  }
   return 0;
 }
 
-int smpi_coll_tuned_alltoall_3dmesh(void * send_buff, int send_count, MPI_Datatype send_type,
-                     void * recv_buff, int recv_count, MPI_Datatype recv_type,
-                     MPI_Comm comm)
+int smpi_coll_tuned_alltoall_3dmesh(void *send_buff, int send_count,
+                                    MPI_Datatype send_type,
+                                    void *recv_buff, int recv_count,
+                                    MPI_Datatype recv_type, MPI_Comm comm)
 {
-  MPI_Request * reqs, * req_ptr;
+  MPI_Request *reqs, *req_ptr;
   MPI_Aint extent;
-  MPI_Status status, * statuses;
+  MPI_Status status, *statuses;
   int i, j, src, dst, rank, num_procs, num_reqs, X, Y, Z, block_size, count;
   int my_z, two_dsize, my_row_base, my_col_base, my_z_base, src_row_base;
-  int src_z_base, send_offset, recv_offset, tag = 1, failure = 0, success = 1;
+  int src_z_base, send_offset, recv_offset, tag = 1;
 
-  char * tmp_buff1, * tmp_buff2;
+  char *tmp_buff1, *tmp_buff2;
 
-  MPI_Comm_rank(comm, &rank);
-  MPI_Comm_size(comm, &num_procs);
-  MPI_Type_extent(send_type, &extent);
+  rank = smpi_comm_rank(comm);
+  num_procs = smpi_comm_size(comm);
+  extent = smpi_datatype_get_extent(send_type);
 
   if (!alltoall_check_is_3dmesh(num_procs, &X, &Y, &Z))
-     return failure;
+    return MPI_ERR_OTHER;