diff --git a/Makefile b/Makefile index 500e52e7c323cb9a54c31c5d13cfd43a224f1840..75a2e49df9978b6383cf26aa2ad88be12d501164 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,9 @@ CFLAGS = -g -O0 -Wall - all: swiftmpistepsim swiftmpistepsim: swiftmpistepsim.c mpiuse.c mpiuse.h atomic.h cycle.h clocks.h clocks.c - $(CC) $(CFLAGS) -o swiftmpistepsim swiftmpistepsim.c mpiuse.c clocks.c -I/usr/include/mpi -lmpi -lpthread + mpicc $(CFLAGS) -o swiftmpistepsim swiftmpistepsim.c mpiuse.c clocks.c clean: - rm swiftmpistepsim + rm -f swiftmpistepsim diff --git a/swiftmpistepsim.c b/swiftmpistepsim.c index 2c22de58452094ecef9b926f94fd41579708bc52..4232d6171bb67d9f2160b932db26d1c765609adc 100644 --- a/swiftmpistepsim.c +++ b/swiftmpistepsim.c @@ -41,6 +41,9 @@ static int usetics = 1; /* Scale to apply to the size of the messages we send. */ static float messagescale = 1.0; +/* Set a data pattern and check we get this back, slow... */ +static int datacheck = 0; + /* Integer types of send and recv tasks, must match log. */ static const int task_type_send = 22; static const int task_type_recv = 23; @@ -67,6 +70,35 @@ static int volatile todo_send = 0; // XXX need to store this in the data file. static double log_clocks_cpufreq = 2194844448.0; +/** + * @brief fill a data area with a pattern that can be checked for changes. + * + * @param size size of data in bytes. + * @param data the data to fill. + */ +static void datacheck_fill(size_t size, void *data) { + unsigned char *p = (unsigned char *)data; + for (size_t i = 0; i < size; i++) { + p[i] = 170; /* 10101010 in bits. */ + } +} + +/** + * @brief test a filled data area for our pattern. + * + * @param size size of data in bytes. + * @param data the data to fill. + * + * @result 1 on success, 0 otherwise. + */ +static int datacheck_test(size_t size, void *data) { + unsigned char *p = (unsigned char *)data; + for (size_t i = 0; i < size; i++) { + if (p[i] != 170) return 0; + } + return 1; +} + /** * @brief Injection thread, initiates MPI_Isend and MPI_Irecv requests. * @@ -131,6 +163,11 @@ static void *inject_thread(void *arg) { int err = 0; if (log->type == task_type_send) { log->data = calloc(log->size, 1); + + /* Fill data with pattern. */ + if (datacheck) datacheck_fill(log->size, log->data); + + /* And send. */ err = MPI_Isend(log->data, log->size, MPI_BYTE, log->otherrank, log->tag, subtypeMPI_comms[log->subtype], &log->req); @@ -140,6 +177,8 @@ static void *inject_thread(void *arg) { atomic_inc(&todo_send); } else { + + /* Ready to receive. */ log->data = calloc(log->size, 1); err = MPI_Irecv(log->data, log->size, MPI_BYTE, log->otherrank, log->tag, subtypeMPI_comms[log->subtype], &log->req); @@ -232,6 +271,12 @@ static void queue_runner(struct mpiuse_log_entry **logs, int volatile *nr_logs, if (dt > lmaxt) lmaxt = dt; if (res) { + /* Check data sent data is unchanged and received data is as + * expected. */ + if (datacheck && !datacheck_test(log->size, log->data)) { + error("Data mismatch on completion"); + } + /* Done, clean up. */ log->done = 1; log->endtic = getticks(); @@ -402,8 +447,11 @@ int main(int argc, char *argv[]) { /* Handle the command-line, we expect a mpiuse data file to read and various * options. */ int opt; - while ((opt = getopt(argc, argv, "vfs:")) != -1) { + while ((opt = getopt(argc, argv, "vfds:")) != -1) { switch (opt) { + case 'd': + datacheck = 1; + break; case 'f': usetics = 0; break; @@ -455,6 +503,10 @@ int main(int argc, char *argv[]) { message(" "); message(" Using message scale of %f", messagescale); } + if (verbose) { + if (usetics) message("using fast untimed injections"); + if (datacheck) message("checking data pattern on send and recv completion"); + } } /* Make three threads, one for injecting tasks and two to check for