#include #include #define ADIOI_MIN(a, b) ((a) < (b) ? (a) : (b)) // ========== The new algorithm I propose =============================================== long int algo1(long int CO, long int stripe_count, long int nprocs_for_coll) { long int CO_nodes, divisor, avail_cb_nodes; /* Calculate how many IO clients we need */ /* To avoid extent lock conflicts, * avail_cb_nodes should either be a multiple of stripe_count, or divide stripe_count exactly. * so that each OST is accessed by a maximum of CO constant clients. */ if (nprocs_for_coll/stripe_count != 0) /* avail_cb_nodes should be a multiple of stripe_count and the number of procs per OST should be limited to the minimum between nprocs_for_coll/stripe_count and CO e.g. if stripe_count=20, nprocs_for_coll=42 and CO=3 then avail_cb_nodes should be egal to 40 */ avail_cb_nodes = stripe_count * ADIOI_MIN(nprocs_for_coll/stripe_count, CO); else { /* nprocs_for_coll is less than stripe_count */ /* avail_cb_nodes should divide stripe_count */ /* e.g. if stripe_count=60 and nprocs_for_coll=8 then avail_cb_nodes should be egal to 6 */ /* This could be done with : while (stripe_count % avail_cb_nodes != 0) avail_cb_nodes--; but this can be optimized for large values of nprocs_for_coll and stripe_count */ divisor = 2; avail_cb_nodes = 1; /* try to divise */ while (stripe_count >= divisor*divisor) { if ((stripe_count % divisor) == 0) { if (stripe_count/divisor <= nprocs_for_coll) { /* The value is found ! */ avail_cb_nodes = stripe_count/divisor; break; } /* if divisor is less than nprocs_for_coll, divisor is a solution, but it is not sure that it is the best one */ else if (divisor <= nprocs_for_coll) avail_cb_nodes = divisor; } divisor++; } } return avail_cb_nodes; } // ============================== With MPICH2 (With last patch from LiuYing) ==================== long int algo2(long int CO, long int stripe_count, long int nprocs_for_coll) { long int CO_nodes, divisor, avail_cb_nodes, CO_max; CO_max = (nprocs_for_coll - 1)/ stripe_count + 1; CO = ADIOI_MIN(CO_max, CO); /* Calculate how many IO clients we need */ /* To avoid extent lock conflicts, * avail_cb_nodes should divide (stripe_count*CO) exactly, * so that each OST is accessed by only one or more constant clients. */ CO_nodes = stripe_count * CO; avail_cb_nodes = ADIOI_MIN(nprocs_for_coll, CO_nodes); if (avail_cb_nodes < CO_nodes) { do { /* find the divisor of CO_nodes */ divisor = 1; do { divisor ++; } while (CO_nodes % divisor); /* if stripe_count*CO is a prime number, change nothing */ CO_nodes = CO_nodes / divisor; if ((CO_nodes <= avail_cb_nodes) && (CO_nodes != 1)) { avail_cb_nodes = CO_nodes; break; } } while (CO_nodes != 1); } return avail_cb_nodes; } void compare_algorithmes(long int CO, long int stripe_count, long int nprocs_for_coll) { long int avail_cb_nodes1, avail_cb_nodes2; avail_cb_nodes1 = algo1(CO, stripe_count, nprocs_for_coll); avail_cb_nodes2 = algo2(CO, stripe_count, nprocs_for_coll); printf(" %3ld %3ld %3ld %3ld", stripe_count, nprocs_for_coll, CO, avail_cb_nodes1); if (avail_cb_nodes2 != avail_cb_nodes1) printf(" algorithme 2 gives %3ld\n", avail_cb_nodes2); else printf("\n"); } int main(int argc, char **argv) { long int CO, stripe_count, nprocs_for_coll, avail_cb_nodes1, avail_cb_nodes2, prev_avail_cb_nodes=0; if ((argc < 3) || (argc > 4)) { printf("usage: cb_nodes stripe_count nprocs_for_coll [CO]\n"); return -1; } stripe_count = strtol(argv[1],0,10); nprocs_for_coll = strtol(argv[2],0,10); if (argc == 4) CO = strtol(argv[3],0,10); else CO = 1; printf("stripe_count nprocs_for_coll CO avail_cb_nodes DIFFERENCES\n"); if (stripe_count && nprocs_for_coll && CO) { compare_algorithmes(CO, stripe_count, nprocs_for_coll); } else { for (CO = 1; CO < 6; CO++) { for (stripe_count = 1; stripe_count < 130; stripe_count++) { for (nprocs_for_coll = 2; nprocs_for_coll < CO*stripe_count+1; nprocs_for_coll++) { compare_algorithmes(CO, stripe_count, nprocs_for_coll); } } } } }