[mpich2-commits] r4163 - in mpich2/trunk/src/pm/hydra: . utils/bind

balaji at mcs.anl.gov balaji at mcs.anl.gov
Sun Mar 22 19:23:20 CDT 2009


Author: balaji
Date: 2009-03-22 19:23:20 -0500 (Sun, 22 Mar 2009)
New Revision: 4163

Modified:
   mpich2/trunk/src/pm/hydra/README
   mpich2/trunk/src/pm/hydra/configure.in
   mpich2/trunk/src/pm/hydra/utils/bind/bind.c
Log:
Modified the process-core binding model to get the topology
information at initialization and just run through the arrays when we
actually need to search for the next core. Also, got rid of the use of
plpa_map_to_processor_id() which seems to be broken and used other
functions that seem to work better.


Modified: mpich2/trunk/src/pm/hydra/README
===================================================================
--- mpich2/trunk/src/pm/hydra/README	2009-03-22 23:09:37 UTC (rev 4162)
+++ mpich2/trunk/src/pm/hydra/README	2009-03-23 00:23:20 UTC (rev 4163)
@@ -90,9 +90,11 @@
 Process-core binding
 --------------------
 
-We support multiple modes of process-core binding: round-robin ("rr"),
-buddy-allocation ("buddy"), closest packing ("pack") and user-defined
-("user"). These can be selected as follows:
+To configure hydra with process-core binding support, use the
+configure option --enable-hydra-procbind. We support multiple modes of
+process-core binding: round-robin ("rr"), buddy-allocation ("buddy"),
+closest packing ("pack") and user-defined ("user"). These can be
+selected as follows:
 
  $ mpiexec --binding rr -f hosts -n 8 ./app
 
@@ -110,7 +112,7 @@
 | |  _____   _____  |  |  _____   _____  | |    | |  _____   _____  |  |  _____   _____  | |
 | | |     | |     | |  | |     | |     | | |    | | |     | |     | |  | |     | |     | | |
 | | |     | |     | |  | |     | |     | | |    | | |     | |     | |  | |     | |     | | | 
-| | |  0  | |  2  | |  | |  1  | |  3  | | |    | | |  0  | |  1  | |  | |  2  | |  3  | | |
+| | |  0  | |  2  | |  | |  1  | |  3  | | |    | | |  0  | |  2  | |  | |  1  | |  3  | | |
 | | |     | |     | |  | |     | |     | | |    | | |     | |     | |  | |     | |     | | |
 | | |_____| |_____| |  | |_____| |_____| | |    | | |_____| |_____| |  | |_____| |_____| | |
 | |_________________|  |_________________| |    | |_________________|  |_________________| |
@@ -130,11 +132,12 @@
 
  $ mpiexec --binding user:0,3 -f hosts -n 4 ./app
 
-In this case, the first two processes are bound to the processing
-elements specified, while the last two are not bound at all. The
-mapping is the same for all machines, so if the application is run
-with 8 processes, the first 2 processes on "each machine" are bound to
-processing elements as specified.
+If a machine has 4 processing elements, and only two bindings are
+provided (as in the above example), the rest are padded with (-1),
+which refers to no binding. Also, the mapping is the same for all
+machines; so if the application is run with 8 processes, the first 2
+processes on "each machine" are bound to processing elements as
+specified.
 
 The host-file based mode for user-defined binding can be used by the
 "map=" argument on each host line. E.g.:

Modified: mpich2/trunk/src/pm/hydra/configure.in
===================================================================
--- mpich2/trunk/src/pm/hydra/configure.in	2009-03-22 23:09:37 UTC (rev 4162)
+++ mpich2/trunk/src/pm/hydra/configure.in	2009-03-23 00:23:20 UTC (rev 4163)
@@ -149,9 +149,9 @@
 fi
 
 dnl Process Binding
-AC_ARG_ENABLE(process-binding, [  --enable-process-binding       Process Binding],
-			       [ PROC_BINDING=$enableval ],
-			       [ PROC_BINDING=no ])
+AC_ARG_ENABLE(hydra-procbind, [  --enable-hydra-procbind       Process Binding],
+			      [ PROC_BINDING=$enableval ],
+			      [ PROC_BINDING=no ])
 AC_MSG_CHECKING(process binding)
 AC_MSG_RESULT($PROC_BINDING)
 if test "$PROC_BINDING" = "yes"; then

Modified: mpich2/trunk/src/pm/hydra/utils/bind/bind.c
===================================================================
--- mpich2/trunk/src/pm/hydra/utils/bind/bind.c	2009-03-22 23:09:37 UTC (rev 4162)
+++ mpich2/trunk/src/pm/hydra/utils/bind/bind.c	2009-03-23 00:23:20 UTC (rev 4163)
@@ -6,22 +6,23 @@
 
 #include "hydra_utils.h"
 
-struct HYDU_bind_info {
+static struct bind_info {
     int supported;
     int num_procs;
     int num_sockets;
     int num_cores;
-};
 
-static struct HYDU_bind_info HYDU_bind_info = { 0, -1, -1, -1 };
+    int **bind_map;
+} bind_info = { 0, -1, -1, -1 , NULL };
 
 HYD_Status HYDU_bind_init(void)
 {
     PLPA_NAME(api_type_t) p;
-    int ret, supported;
+    int ret, supported, i, j;
     int num_procs, max_proc_id;
     int num_sockets = -1, max_socket_id;
     int num_cores = -1, max_core_id;
+    int socket, core;
     HYD_Status status = HYD_SUCCESS;
 
     HYDU_FUNC_ENTER();
@@ -55,6 +56,21 @@
             HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR,
                                 "plpa get processor data failed\n");
         }
+
+        HYDU_MALLOC(bind_info.bind_map, int **, num_sockets * sizeof(int *), status);
+        for (i = 0; i < num_sockets; i++) {
+            HYDU_MALLOC(bind_info.bind_map[i], int *, num_cores * sizeof(int), status);
+            for (j = 0; j < num_cores; j++)
+                bind_info.bind_map[i][j] = -1;
+        }
+
+        for (i = 0; i < num_sockets * num_cores; i++) {
+            ret = PLPA_NAME(map_to_socket_core)(i, &socket, &core);
+            if (ret)
+                HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR,
+                                    "plpa map_to_socket_core failed\n");
+            bind_info.bind_map[socket][core] = i;
+        }
     }
     else {
         /* If this failed, we just return without binding */
@@ -62,10 +78,10 @@
         goto fn_exit;
     }
 
-    HYDU_bind_info.supported = 1;
-    HYDU_bind_info.num_procs = num_procs;
-    HYDU_bind_info.num_sockets = num_sockets;
-    HYDU_bind_info.num_cores = num_cores;
+    bind_info.supported = 1;
+    bind_info.num_procs = num_procs;
+    bind_info.num_sockets = num_sockets;
+    bind_info.num_cores = num_cores;
 
   fn_exit:
     HYDU_FUNC_EXIT();
@@ -83,9 +99,9 @@
 
     HYDU_FUNC_ENTER();
 
-    if (HYDU_bind_info.supported) {
+    if (bind_info.supported) {
         PLPA_NAME_CAPS(CPU_ZERO)(&cpuset);
-        PLPA_NAME_CAPS(CPU_SET)(core % HYDU_bind_info.num_procs, &cpuset);
+        PLPA_NAME_CAPS(CPU_SET)(core % bind_info.num_procs, &cpuset);
         ret = PLPA_NAME(sched_setaffinity)(0, 1, &cpuset);
         if (ret)
             HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "plpa setaffinity failed\n");
@@ -103,65 +119,81 @@
 int HYDU_next_core(int old_core, HYD_Binding binding)
 {
     int socket, core, proc;
-    int ret, new_core = -1, found;
+    int ret;
     HYD_Status status = HYD_SUCCESS;
 
     HYDU_FUNC_ENTER();
 
-    /* Round-robin is easy; just give the next core */
-    if (HYDU_bind_info.supported) {
+    if (bind_info.supported) {
         if (binding == HYD_BIND_RR) {
-            return (old_core + 1);
+            /* Round-robin is easy; just give the next core */
+            return ((old_core + 1) % (bind_info.num_sockets * bind_info.num_cores));
         }
         else if (binding == HYD_BIND_BUDDY) {
-            found = 0;
-            for (core = 0; core < HYDU_bind_info.num_cores; core++)
-                for (socket = 0; socket < HYDU_bind_info.num_sockets; socket++) {
-                    ret = PLPA_NAME(map_to_processor_id)(socket, core, &proc);
-                    if (ret)
-                        HYDU_ERR_SETANDJUMP2(status, HYD_INTERNAL_ERROR,
-                                             "plpa map_to_proc_id failed (%d,%d)\n",
-                                             socket, core);
+            if (old_core == -1)
+                return 0;
 
-                    if (found)
-                        return proc;
-                    else if (proc != core)
-                        continue;
-                    else
-                        found = 1;
+            /* First find the old core */
+            for (core = 0; core < bind_info.num_cores; core++) {
+                for (socket = 0; socket < bind_info.num_sockets; socket++) {
+                    if (bind_info.bind_map[socket][core] == old_core)
+                        break;
                 }
+                if (bind_info.bind_map[socket][core] == old_core)
+                    break;
+            }
 
-            return -1;
+            /* If there is another socket available after this, give
+             * the same core ID on that socket */
+            if (socket < bind_info.num_sockets - 1)
+                return bind_info.bind_map[socket+1][core];
+            /* If we are the last socket, and there is a core left
+             * after ours, give that core on the first socket */
+            else if (core < bind_info.num_cores - 1)
+                return bind_info.bind_map[0][core+1];
+            /* If we are the last socket and last core, loop back to
+             * the start */
+            else
+                return bind_info.bind_map[0][0];
         }
         else if (binding == HYD_BIND_PACK) {
-            found = 0;
-            for (socket = 0; socket < HYDU_bind_info.num_sockets; socket++) {
-                for (core = 0; core < HYDU_bind_info.num_cores; core++)
-                    ret = PLPA_NAME(map_to_processor_id)(socket, core, &proc);
-                    if (ret)
-                        HYDU_ERR_SETANDJUMP2(status, HYD_INTERNAL_ERROR,
-                                             "plpa map_to_proc_id failed (%d,%d)\n",
-                                             socket, core);
+            if (old_core == -1)
+                return 0;
 
-                    if (found)
-                        return proc;
-                    else if (proc != core)
-                        continue;
-                    else
-                        found = 1;
+            /* First find the old core */
+            for (core = 0; core < bind_info.num_cores; core++) {
+                for (socket = 0; socket < bind_info.num_sockets; socket++) {
+                    if (bind_info.bind_map[socket][core] == old_core)
+                        break;
                 }
+                if (bind_info.bind_map[socket][core] == old_core)
+                    break;
+            }
 
-            return -1;
+            /* If there is another core available after this, give
+             * that core ID on the same socket */
+            if (core < bind_info.num_cores - 1)
+                return bind_info.bind_map[socket][core+1];
+            /* If we are the last core, and there is a socket left
+             * after ours, give the first core on that socket */
+            else if (socket < bind_info.num_sockets - 1)
+                return bind_info.bind_map[socket+1][0];
+            /* If we are the last socket and last core, loop back to
+             * the start */
+            else
+                return bind_info.bind_map[0][0];
         }
         else
             return -1;
     }
+    else {
+        HYDU_Error_printf("Process-core binding is not supported on this platform\n");
+    }
 
   fn_exit:
     HYDU_FUNC_EXIT();
-    return new_core;
+    return -1;
 
   fn_fail:
-    new_core = -1;
     goto fn_exit;
 }



More information about the mpich2-commits mailing list