|
Packit |
857059 |
/* BEGIN_ICS_COPYRIGHT7 ****************************************
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Copyright (c) 2015, Intel Corporation
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
857059 |
modification, are permitted provided that the following conditions are met:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
* Redistributions of source code must retain the above copyright notice,
|
|
Packit |
857059 |
this list of conditions and the following disclaimer.
|
|
Packit |
857059 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
857059 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
857059 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
857059 |
* Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
857059 |
may be used to endorse or promote products derived from this software
|
|
Packit |
857059 |
without specific prior written permission.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
857059 |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
857059 |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
Packit |
857059 |
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
Packit |
857059 |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
857059 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
Packit |
857059 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
Packit |
857059 |
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit |
857059 |
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
857059 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
** END_ICS_COPYRIGHT7 ****************************************/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* [ICS VERSION STRING: unknown] */
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Copyright (C) 2002-2005 the Network-Based Computing Laboratory
|
|
Packit |
857059 |
* (NBCL), The Ohio State University.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Contact: Dr. D. K. Panda (panda@cse.ohio-state.edu)
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
This program is available under BSD licensing.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
857059 |
modification, are permitted provided that the following conditions are
|
|
Packit |
857059 |
met:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
(1) Redistributions of source code must retain the above copyright
|
|
Packit |
857059 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
(2) Redistributions in binary form must reproduce the above copyright
|
|
Packit |
857059 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
857059 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
(3) Neither the name of The Ohio State University nor the names of
|
|
Packit |
857059 |
their contributors may be used to endorse or promote products derived
|
|
Packit |
857059 |
from this software without specific prior written permission.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
857059 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
857059 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
857059 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit |
857059 |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit |
857059 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
857059 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit |
857059 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit |
857059 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
857059 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
857059 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* mpi_latencystress
|
|
Packit |
857059 |
|
|
Packit |
857059 |
The purpose of this program is to stress links in a large IB fabric.
|
|
Packit |
857059 |
While it generates some basic numbers about how the links
|
|
Packit |
857059 |
are performing, it is not intended as a benchmark.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#include "mpi.h"
|
|
Packit |
857059 |
#include <stdio.h>
|
|
Packit |
857059 |
#include <unistd.h>
|
|
Packit |
857059 |
#include <getopt.h>
|
|
Packit |
857059 |
#include <stdlib.h>
|
|
Packit |
857059 |
#include <string.h>
|
|
Packit |
857059 |
#include <math.h>
|
|
Packit |
857059 |
#include <time.h>
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define stringize(x) #x
|
|
Packit |
857059 |
#define add_quotes(x) stringize(x)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define DEBUG(X,...) if (verbose>2) printf(X, ## __VA_ARGS__ )
|
|
Packit |
857059 |
#define VERBOSE(X,...) if (verbose>1) printf(X, ## __VA_ARGS__ )
|
|
Packit |
857059 |
#define NORMAL(X,...) if (verbose>0) printf(X, ## __VA_ARGS__ )
|
|
Packit |
857059 |
#define RANK0(X,...) if (verbose && my_id == 0) printf(X, ## __VA_ARGS__ )
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define MESSAGE_ALIGNMENT 64
|
|
Packit |
857059 |
#define MIN_MSG_SIZE 0
|
|
Packit |
857059 |
#define MAX_MSG_SIZE (1<<22)
|
|
Packit |
857059 |
#define MY_BUF_SIZE (MAX_MSG_SIZE + MESSAGE_ALIGNMENT)
|
|
Packit |
857059 |
#define DEFAULT_MINUTES 5
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define TAG_BASIC 1000
|
|
Packit |
857059 |
#define TAG_RSLT1 1001
|
|
Packit |
857059 |
#define TAG_RSLT2 1002
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Command line args.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
static int minutes = DEFAULT_MINUTES; // how long the test should run.
|
|
Packit |
857059 |
static int verbose = 0; // noisy output
|
|
Packit |
857059 |
static int size = MIN_MSG_SIZE;
|
|
Packit |
857059 |
static int csv = 0; // generate CSV file
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static int num_procs; // how many processes in the job?
|
|
Packit |
857059 |
static int my_id; // my rank.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define PATTERN_SIZE 80
|
|
Packit |
857059 |
static u_int32_t pattern[] = {
|
|
Packit |
857059 |
0x63636363,
|
|
Packit |
857059 |
0xA3A3A3A3,
|
|
Packit |
857059 |
0x54545454,
|
|
Packit |
857059 |
0x47474747,
|
|
Packit |
857059 |
0x18181818,
|
|
Packit |
857059 |
0x63636363,
|
|
Packit |
857059 |
0xA3A3A3A3,
|
|
Packit |
857059 |
0x54545454,
|
|
Packit |
857059 |
0x47474747,
|
|
Packit |
857059 |
0x18181818,
|
|
Packit |
857059 |
0x63636363,
|
|
Packit |
857059 |
0xA3A3A3A3,
|
|
Packit |
857059 |
0x54545454,
|
|
Packit |
857059 |
0x47474747,
|
|
Packit |
857059 |
0x18181818,
|
|
Packit |
857059 |
0x63636363,
|
|
Packit |
857059 |
0xA3A3A3A3,
|
|
Packit |
857059 |
0x54545454,
|
|
Packit |
857059 |
0x47474747,
|
|
Packit |
857059 |
0x18181818,
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
char s_buf1[MY_BUF_SIZE];
|
|
Packit |
857059 |
char r_buf1[MY_BUF_SIZE];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
struct partner {
|
|
Packit |
857059 |
int inuse;
|
|
Packit |
857059 |
int sender;
|
|
Packit |
857059 |
int receiver;
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define MAX_HOST_LEN 32
|
|
Packit |
857059 |
struct host { char name[MAX_HOST_LEN]; };
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static struct partner *pair_list;
|
|
Packit |
857059 |
static struct host *host_list;
|
|
Packit |
857059 |
static short *checked;
|
|
Packit |
857059 |
static double *latency;
|
|
Packit |
857059 |
static unsigned long psize;
|
|
Packit |
857059 |
static unsigned long csize;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static void
|
|
Packit |
857059 |
dump_checked(int ranks)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i, j;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
printf(" ");
|
|
Packit |
857059 |
for (i = 0; i< ranks; i++) {
|
|
Packit |
857059 |
printf(":%4d",i);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
printf("\n");
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (j = 0; j < ranks; j++) {
|
|
Packit |
857059 |
printf("%4d",j);
|
|
Packit |
857059 |
for (i = 0; i < ranks; i++) {
|
|
Packit |
857059 |
if (checked[j*ranks+i]) {
|
|
Packit |
857059 |
printf(": %02u ", checked[j*ranks+i]);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
printf(": ");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
printf("\n");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static int
|
|
Packit |
857059 |
calculate_pairs(int iteration, int ranks)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i,j, k, pairs_found, match_found;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
memset(pair_list,0,psize);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pairs_found = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (iteration > ranks) return 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (i=0; i
|
|
Packit |
857059 |
match_found = 0;
|
|
Packit |
857059 |
if (pair_list[i].inuse == 0) {
|
|
Packit |
857059 |
for (k=ranks-i-iteration; k>i-ranks; k--) {
|
|
Packit |
857059 |
j = (k>=0)?k:(k+ranks);
|
|
Packit |
857059 |
if (i == j) {
|
|
Packit |
857059 |
// Can't test against yourself.
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
} else if ((pair_list[j].inuse == 0) &&
|
|
Packit |
857059 |
(checked[i*ranks+j]==0)) {
|
|
Packit |
857059 |
pair_list[i].inuse=1;
|
|
Packit |
857059 |
pair_list[i].sender=i;
|
|
Packit |
857059 |
pair_list[i].receiver=j;
|
|
Packit |
857059 |
pair_list[j]=pair_list[i];
|
|
Packit |
857059 |
match_found=1;
|
|
Packit |
857059 |
checked[i*ranks+j]=iteration;
|
|
Packit |
857059 |
checked[j*ranks+i]=iteration;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
} else if ((pair_list[j].inuse != 0))
|
|
Packit |
857059 |
DEBUG("collision on [%d,%d] (%d)\n",
|
|
Packit |
857059 |
i, j, k);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if (!match_found) {
|
|
Packit |
857059 |
// This will happen if
|
|
Packit |
857059 |
// ranks is not a power of 2.
|
|
Packit |
857059 |
pair_list[i].sender=-1;
|
|
Packit |
857059 |
pair_list[i].receiver=-1;
|
|
Packit |
857059 |
pair_list[i].inuse=1;
|
|
Packit |
857059 |
VERBOSE("%d is idle this iteration.\n", i);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
pairs_found++;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return pairs_found;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Taken from osu_latency and converted to a function.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int skip = 1000;
|
|
Packit |
857059 |
int loop = 10000;
|
|
Packit |
857059 |
int skip_large = 10;
|
|
Packit |
857059 |
int loop_large = 100;
|
|
Packit |
857059 |
int large_message_size = 8192;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static void
|
|
Packit |
857059 |
find_latency(int ranks, int size, char *s_buf, char *r_buf,
|
|
Packit |
857059 |
double *min_lat, double *max_lat, double *avg_lat,
|
|
Packit |
857059 |
int *min_rank, int *max_rank)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i;
|
|
Packit |
857059 |
MPI_Status reqstat;
|
|
Packit |
857059 |
MPI_Comm mpi_comm_sender;
|
|
Packit |
857059 |
MPI_Request request1, request2;
|
|
Packit |
857059 |
int partner;
|
|
Packit |
857059 |
double lat;
|
|
Packit |
857059 |
double summary_f[3];
|
|
Packit |
857059 |
int summary_i[2];
|
|
Packit |
857059 |
int sender_id;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
double t_start = 0.0, t_end = 0.0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//VERBOSE("%d @ find_latency(%d, %d, %p, %p)\n",
|
|
Packit |
857059 |
// my_id, ranks, size, s_buf, r_buf);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pair_list[my_id].sender == my_id) {
|
|
Packit |
857059 |
partner = pair_list[my_id].receiver;
|
|
Packit |
857059 |
//VERBOSE("%d -> %d\n", my_id, partner);
|
|
Packit |
857059 |
} else if (pair_list[my_id].receiver == my_id) {
|
|
Packit |
857059 |
partner = pair_list[my_id].sender;
|
|
Packit |
857059 |
//VERBOSE("%d <- %d\n", my_id, partner);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
//VERBOSE("%d IDLE\n",my_id);
|
|
Packit |
857059 |
partner = -1;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//VERBOSE("%d @ buffers loaded.\n",my_id);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (size > large_message_size) {
|
|
Packit |
857059 |
loop = loop_large;
|
|
Packit |
857059 |
skip = skip_large;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// VERBOSE("%d @ barrier.\n", my_id);
|
|
Packit |
857059 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pair_list[my_id].sender == my_id) {
|
|
Packit |
857059 |
// VERBOSE("%d @ sending.\n", my_id);
|
|
Packit |
857059 |
MPI_Comm_split(MPI_COMM_WORLD, 1, my_id, &mpi_comm_sender);
|
|
Packit |
857059 |
for (i = 0; i < loop + skip; i++) {
|
|
Packit |
857059 |
if (i == skip)
|
|
Packit |
857059 |
t_start = MPI_Wtime();
|
|
Packit |
857059 |
MPI_Send(s_buf,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
partner,
|
|
Packit |
857059 |
TAG_BASIC,
|
|
Packit |
857059 |
MPI_COMM_WORLD);
|
|
Packit |
857059 |
MPI_Recv(r_buf,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
partner,
|
|
Packit |
857059 |
TAG_BASIC,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&reqstat);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
t_end = MPI_Wtime();
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} else if (pair_list[my_id].receiver == my_id) {
|
|
Packit |
857059 |
// VERBOSE("%d @ receiving.\n", my_id);
|
|
Packit |
857059 |
MPI_Comm_split(MPI_COMM_WORLD, 2, my_id, &mpi_comm_sender);
|
|
Packit |
857059 |
for (i = 0; i < loop + skip; i++) {
|
|
Packit |
857059 |
MPI_Recv(r_buf,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
partner,
|
|
Packit |
857059 |
TAG_BASIC,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&reqstat);
|
|
Packit |
857059 |
MPI_Send(s_buf,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
partner,
|
|
Packit |
857059 |
TAG_BASIC,
|
|
Packit |
857059 |
MPI_COMM_WORLD);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
MPI_Comm_split(MPI_COMM_WORLD, 3, my_id, &mpi_comm_sender);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// VERBOSE("%d @ collectives.\n", my_id);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pair_list[my_id].sender == my_id) {
|
|
Packit |
857059 |
lat = (t_end - t_start) * 1.0e6 / (2.0 * loop);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
VERBOSE("t_start = %f, t_end = %f, loop = %d, lat = %f\n", t_start, t_end, loop, lat);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Reduce(&lat, &summary_f[0], 1, MPI_DOUBLE, MPI_MIN, 0, mpi_comm_sender);
|
|
Packit |
857059 |
MPI_Reduce(&lat, &summary_f[1], 1, MPI_DOUBLE, MPI_MAX, 0, mpi_comm_sender);
|
|
Packit |
857059 |
MPI_Reduce(&lat, &summary_f[2], 1, MPI_DOUBLE, MPI_SUM, 0, mpi_comm_sender);
|
|
Packit |
857059 |
MPI_Gather(&lat, 1, MPI_DOUBLE, latency, 1, MPI_DOUBLE, 0, mpi_comm_sender);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Comm_rank(mpi_comm_sender, &sender_id);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
sender_id = -1;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// It is possible for the root of the senders to be different from
|
|
Packit |
857059 |
// the global rank 0. So, the root of the senders will send
|
|
Packit |
857059 |
// a summary of the results to rank 0, even though this is usually
|
|
Packit |
857059 |
// redundant.
|
|
Packit |
857059 |
if (sender_id == 0) {
|
|
Packit |
857059 |
int j=0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (i=0;i
|
|
Packit |
857059 |
// note that ranks in mpi_comm_sender do NOT match
|
|
Packit |
857059 |
// ranks in MPI_COMM_WORLD. We need to only show
|
|
Packit |
857059 |
// the ranks that actually send data this iteration.
|
|
Packit |
857059 |
if (pair_list[i].sender == i) {
|
|
Packit |
857059 |
if (csv) {
|
|
Packit |
857059 |
printf("%s, %d, %s, %d, %0.2f\n",
|
|
Packit |
857059 |
host_list[pair_list[i].sender].name, pair_list[i].sender,
|
|
Packit |
857059 |
host_list[pair_list[i].receiver].name, pair_list[i].receiver,
|
|
Packit |
857059 |
latency[j]);
|
|
Packit |
857059 |
fflush(stdout);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
// The following bit of jiggery-pokery is so I can identify which rank was
|
|
Packit |
857059 |
// slowest and which was fastest.
|
|
Packit |
857059 |
if (latency[j] == summary_f[0]) {
|
|
Packit |
857059 |
summary_i[0] = i;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if (latency[j] == summary_f[1]) {
|
|
Packit |
857059 |
summary_i[1] = i;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
j++;
|
|
Packit |
857059 |
//} else if (pair_list[i].sender == -1) {
|
|
Packit |
857059 |
// NORMAL("%"add_quotes(MAX_HOST_LEN)"s[%d] -> idle\n", host_list[i].name, i);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
summary_f[2] = (j)?(summary_f[2] / j):0.0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Isend(summary_f,
|
|
Packit |
857059 |
3,
|
|
Packit |
857059 |
MPI_DOUBLE,
|
|
Packit |
857059 |
0,
|
|
Packit |
857059 |
TAG_RSLT1,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&request1);
|
|
Packit |
857059 |
MPI_Isend(summary_i,
|
|
Packit |
857059 |
2,
|
|
Packit |
857059 |
MPI_INT,
|
|
Packit |
857059 |
0,
|
|
Packit |
857059 |
TAG_RSLT2,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&request2);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (my_id == 0) {
|
|
Packit |
857059 |
MPI_Recv(summary_f,
|
|
Packit |
857059 |
3,
|
|
Packit |
857059 |
MPI_DOUBLE,
|
|
Packit |
857059 |
MPI_ANY_SOURCE,
|
|
Packit |
857059 |
TAG_RSLT1,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&reqstat);
|
|
Packit |
857059 |
MPI_Recv(summary_i,
|
|
Packit |
857059 |
2,
|
|
Packit |
857059 |
MPI_INT,
|
|
Packit |
857059 |
MPI_ANY_SOURCE,
|
|
Packit |
857059 |
TAG_RSLT2,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&reqstat);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
*min_lat = summary_f[0];
|
|
Packit |
857059 |
*max_lat = summary_f[1];
|
|
Packit |
857059 |
*avg_lat = summary_f[2];
|
|
Packit |
857059 |
*min_rank = summary_i[0];
|
|
Packit |
857059 |
*max_rank = summary_i[1];
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
857059 |
MPI_Comm_free(&mpi_comm_sender);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//VERBOSE("%d @ done.\n", my_id);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static char *short_options = "s:vt:ch";
|
|
Packit |
857059 |
static struct option long_options[] = {
|
|
Packit |
857059 |
{ .name = "verbose", .has_arg = 0, .val = 'v' },
|
|
Packit |
857059 |
{ .name = "size", .has_arg = 0, .val = 's' },
|
|
Packit |
857059 |
{ .name = "time", .has_arg = 1, .val = 't' },
|
|
Packit |
857059 |
{ .name = "csv", . has_arg = 0, .val = 'c' },
|
|
Packit |
857059 |
{ .name = "help", .has_arg = 0, .val = 'h' },
|
|
Packit |
857059 |
{ 0 }
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static char *usage_text[] = {
|
|
Packit |
857059 |
"Verbose. Outputs some debugging information. Use multiple times for more detailed information.",
|
|
Packit |
857059 |
"Message Size. Should be between " add_quotes(MIN_MSG_SIZE) " and " add_quotes(MAX_MSG_SIZE),
|
|
Packit |
857059 |
"The duration of the test, in minutes. Defaults to "
|
|
Packit |
857059 |
add_quotes(DEFAULT_MINUTES) " minutes or use -1 to run forever.",
|
|
Packit |
857059 |
"Outputs raw data in a CSV file format, suitable for use in Excel."
|
|
Packit |
857059 |
"Provides this help text.",
|
|
Packit |
857059 |
0
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static void
|
|
Packit |
857059 |
usage()
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i=0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (my_id == 0) {
|
|
Packit |
857059 |
fprintf(stderr,"\nError processing command line arguments.\n\n");
|
|
Packit |
857059 |
fprintf(stderr,"USAGE:\n");
|
|
Packit |
857059 |
while (long_options[i].name != NULL) {
|
|
Packit |
857059 |
fprintf(stderr, " -%c/--%-8s %s %s\n",
|
|
Packit |
857059 |
long_options[i].val,
|
|
Packit |
857059 |
long_options[i].name,
|
|
Packit |
857059 |
(long_options[i].has_arg)?"<arg>":" ",
|
|
Packit |
857059 |
usage_text[i]);
|
|
Packit |
857059 |
i++;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
fprintf(stderr,"\n\n");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int
|
|
Packit |
857059 |
main(int argc, char *argv[])
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int done = 0;
|
|
Packit |
857059 |
int err = 0;
|
|
Packit |
857059 |
int c, i;
|
|
Packit |
857059 |
int align_size = MESSAGE_ALIGNMENT;
|
|
Packit |
857059 |
time_t done_time;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//int DebugWait = 1; // used to attach gdb.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
char *s_buf = (char*)(((unsigned long)s_buf1 + (align_size - 1)) /
|
|
Packit |
857059 |
align_size * align_size);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
char *r_buf = (char*)(((unsigned long)s_buf1 + (align_size - 1)) /
|
|
Packit |
857059 |
align_size * align_size);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
memset(r_buf1,'a',MY_BUF_SIZE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for(c=0;c<(MAX_MSG_SIZE-PATTERN_SIZE);c+=PATTERN_SIZE)
|
|
Packit |
857059 |
memcpy(s_buf+c,pattern,PATTERN_SIZE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int min_rank, max_rank, num_pairs;
|
|
Packit |
857059 |
struct partner round_fastest, round_slowest;
|
|
Packit |
857059 |
int found_fastest = 0;
|
|
Packit |
857059 |
int found_slowest = 0;
|
|
Packit |
857059 |
double min_lat, max_lat;
|
|
Packit |
857059 |
double avg_lat = 0;
|
|
Packit |
857059 |
double final_min = 99999999.0, final_max = 0.0;
|
|
Packit |
857059 |
double round_min, round_max;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Init(&argc, &argv);
|
|
Packit |
857059 |
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
|
Packit |
857059 |
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//if (my_id == 0) while (DebugWait); // used to attach gdb.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
while ( -1 != (c = getopt_long(argc, argv, short_options, long_options, NULL))) {
|
|
Packit |
857059 |
switch (c) {
|
|
Packit |
857059 |
case 'v':
|
|
Packit |
857059 |
verbose += 1;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case 's':
|
|
Packit |
857059 |
size = strtoul(optarg, NULL, 0);
|
|
Packit |
857059 |
if (size < MIN_MSG_SIZE || size > MAX_MSG_SIZE) {
|
|
Packit |
857059 |
usage();
|
|
Packit |
857059 |
err = -1;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case 't':
|
|
Packit |
857059 |
minutes = strtol(optarg, NULL, 0);
|
|
Packit |
857059 |
if (minutes == 0 && strcmp(optarg,"0")) {
|
|
Packit |
857059 |
usage();
|
|
Packit |
857059 |
err = -1;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case 'c':
|
|
Packit |
857059 |
csv = 1;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
case 'h':
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
usage();
|
|
Packit |
857059 |
err = -1;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
RANK0("Allocating buffers.\n");
|
|
Packit |
857059 |
psize = sizeof (struct partner) * num_procs;
|
|
Packit |
857059 |
pair_list = malloc(psize);
|
|
Packit |
857059 |
csize = sizeof(short) * num_procs * num_procs;
|
|
Packit |
857059 |
checked = malloc(csize);
|
|
Packit |
857059 |
latency = malloc(sizeof(double)*num_procs);
|
|
Packit |
857059 |
host_list = malloc(sizeof(struct host)*num_procs);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!pair_list || !checked || !latency || !host_list) {
|
|
Packit |
857059 |
fprintf(stderr,"malloc failed.\n");
|
|
Packit |
857059 |
err = -1;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Broadcast the hostnames.
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
struct host myname;
|
|
Packit |
857059 |
gethostname(myname.name, MAX_HOST_LEN-1);
|
|
Packit |
857059 |
myname.name[MAX_HOST_LEN-1]='\0';
|
|
Packit |
857059 |
//VERBOSE("%d hostname: %s\n",my_id,myname.name);
|
|
Packit |
857059 |
memset(host_list, 0, sizeof(struct host)*num_procs);
|
|
Packit |
857059 |
MPI_Allgather(&myname, sizeof(myname), MPI_CHAR, host_list, sizeof(myname), MPI_CHAR, MPI_COMM_WORLD);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (my_id == 0) {
|
|
Packit |
857059 |
if (minutes > 0) {
|
|
Packit |
857059 |
done_time = time(NULL) + minutes*60;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
done_time = (time_t)-1;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
do {
|
|
Packit |
857059 |
memset(checked,0,csize);
|
|
Packit |
857059 |
if ((my_id == 0) && !csv) {
|
|
Packit |
857059 |
printf("\n\nMPI HCA Latency Stress Test\n");
|
|
Packit |
857059 |
printf("Msg Size:\t%d\n",size);
|
|
Packit |
857059 |
if (minutes > 0) {
|
|
Packit |
857059 |
long rt = done_time-time(NULL);
|
|
Packit |
857059 |
if (rt > 3600) {
|
|
Packit |
857059 |
printf("Time Left:\t%ld hours and %ld minutes\n",
|
|
Packit |
857059 |
rt/3600,
|
|
Packit |
857059 |
rt/60 - (rt/3600)*60);
|
|
Packit |
857059 |
} else if (rt > 60) {
|
|
Packit |
857059 |
printf("Time Left:\t%ld minutes and %ld seconds\n",rt/60,
|
|
Packit |
857059 |
rt - (rt/60)*60);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
printf("Time Left:\t%ld seconds\n",(rt > 0)?rt:0);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
printf("Time Left:\ttil interrupted.\n");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
round_max = 0.0;
|
|
Packit |
857059 |
round_min = 99999999.0;
|
|
Packit |
857059 |
num_pairs = 1;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (i=1; num_pairs > 0; i++) {
|
|
Packit |
857059 |
if (my_id == 0) {
|
|
Packit |
857059 |
// Rank 0 calculates the pairs and distributes the
|
|
Packit |
857059 |
// info to other nodes.
|
|
Packit |
857059 |
int j;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (j=0;j
|
|
Packit |
857059 |
latency[j]=-1.0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
NORMAL("Iteration #%d\n",i);
|
|
Packit |
857059 |
num_pairs = calculate_pairs(i, num_procs);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If we found no pairs to test, time to stop.
|
|
Packit |
857059 |
if (num_pairs == 0) {
|
|
Packit |
857059 |
NORMAL("No pairs left to test.\n");
|
|
Packit |
857059 |
pair_list[0].inuse = -2;
|
|
Packit |
857059 |
if (verbose>1) dump_checked(num_procs);
|
|
Packit |
857059 |
} else if (verbose>2) {
|
|
Packit |
857059 |
dump_checked(num_procs);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Bcast(pair_list,
|
|
Packit |
857059 |
psize,
|
|
Packit |
857059 |
MPI_UNSIGNED_CHAR,
|
|
Packit |
857059 |
0,
|
|
Packit |
857059 |
MPI_COMM_WORLD);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If rank 0 says there are no pairs to test,
|
|
Packit |
857059 |
// then it's time to stop.
|
|
Packit |
857059 |
if (pair_list[0].inuse == -2) {
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
find_latency(num_procs,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
s_buf,
|
|
Packit |
857059 |
r_buf,
|
|
Packit |
857059 |
&min_lat,
|
|
Packit |
857059 |
&max_lat,
|
|
Packit |
857059 |
&avg_lat,
|
|
Packit |
857059 |
&min_rank,
|
|
Packit |
857059 |
&max_rank);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (my_id == 0 && min_lat < round_min) {
|
|
Packit |
857059 |
round_min = min_lat;
|
|
Packit |
857059 |
round_fastest = pair_list[min_rank];
|
|
Packit |
857059 |
found_fastest=1;
|
|
Packit |
857059 |
if (round_min < final_min) final_min = round_min;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if (my_id == 0 && max_lat > round_max) {
|
|
Packit |
857059 |
round_max = max_lat;
|
|
Packit |
857059 |
round_slowest = pair_list[max_rank];
|
|
Packit |
857059 |
found_slowest = 1;
|
|
Packit |
857059 |
if (round_max > final_max) final_max = round_max;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Barrier(MPI_COMM_WORLD);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (my_id == 0) {
|
|
Packit |
857059 |
if (!csv) {
|
|
Packit |
857059 |
printf("Avg Latency:\t%0.2f\n",avg_lat);
|
|
Packit |
857059 |
if(found_fastest) {
|
|
Packit |
857059 |
printf("Fastest Pair:\n%"add_quotes(MAX_HOST_LEN)"s -> %"add_quotes(MAX_HOST_LEN)"s\t%0.2f\n",
|
|
Packit |
857059 |
host_list[round_fastest.sender].name,
|
|
Packit |
857059 |
host_list[round_fastest.receiver].name,
|
|
Packit |
857059 |
round_min);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if(found_slowest) {
|
|
Packit |
857059 |
printf("Slowest Pair:\n%"add_quotes(MAX_HOST_LEN)"s -> %"add_quotes(MAX_HOST_LEN)"s\t%0.2f\n",
|
|
Packit |
857059 |
host_list[round_slowest.sender].name,
|
|
Packit |
857059 |
host_list[round_slowest.receiver].name,
|
|
Packit |
857059 |
round_max);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
done = (minutes > 0) && (done_time < time(NULL));
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
MPI_Bcast(&done,1,MPI_INT,0,MPI_COMM_WORLD);
|
|
Packit |
857059 |
} while (!done);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (my_id == 0) {
|
|
Packit |
857059 |
fprintf(stderr,"\n\nMPI HCA Latency Stress Test\n");
|
|
Packit |
857059 |
fprintf(stderr,"Msg Size:\t%d\n",size);
|
|
Packit |
857059 |
fprintf(stderr,"Final Min:\t%0.2f\n",final_min);
|
|
Packit |
857059 |
fprintf(stderr,"Final Max:\t%0.2f\n",final_max);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
exit:
|
|
Packit |
857059 |
//VERBOSE("%d at finalize.\n",my_id);
|
|
Packit |
857059 |
MPI_Finalize();
|
|
Packit |
857059 |
return err;
|
|
Packit |
857059 |
}
|