Skip to content
Snippets Groups Projects
Verified Commit bcf26d11 authored by Dorian Stoll's avatar Dorian Stoll
Browse files

zellularautomat: c: Drop MPI version

parent cdd4bac2
No related branches found
No related tags found
No related merge requests found
BASE_CC=gcc BASE_CC=gcc
MPI_CC=mpicc
COMMON_CFLAGS=-O2 COMMON_CFLAGS=-O2
COMMON_LDFLAGS=-lcrypto -lrt COMMON_LDFLAGS=-lcrypto -lrt
...@@ -8,15 +7,10 @@ BASE_CFLAGS=-Wall -std=gnu99 -pedantic ...@@ -8,15 +7,10 @@ BASE_CFLAGS=-Wall -std=gnu99 -pedantic
OMP_CFLAGS=-fopenmp OMP_CFLAGS=-fopenmp
MPI_CFLAGS=-DUSE_MPI
C_DEPS=ca_common.c random.c C_DEPS=ca_common.c random.c
MPI_TARGETS=ca_mpi_p2p ca_mpi_p2p_hybrid
TARGETS=ca_seq \ TARGETS=ca_seq \
ca_openmp \ ca_openmp
$(MPI_TARGETS)
.PHONY: all .PHONY: all
all: $(TARGETS) all: $(TARGETS)
...@@ -24,21 +18,12 @@ all: $(TARGETS) ...@@ -24,21 +18,12 @@ all: $(TARGETS)
.PHONY: cpu .PHONY: cpu
cpu: ca_seq ca_openmp cpu: ca_seq ca_openmp
.PHONY: mpi
mpi: $(MPI_TARGETS)
ca_seq: ca_seq.c $(C_DEPS) ca_seq: ca_seq.c $(C_DEPS)
$(BASE_CC) $(COMMON_CFLAGS) $(BASE_CFLAGS) $^ $(COMMON_LDFLAGS) -o $@ $(BASE_CC) $(COMMON_CFLAGS) $(BASE_CFLAGS) $^ $(COMMON_LDFLAGS) -o $@
ca_openmp: ca_openmp.c $(C_DEPS) ca_openmp: ca_openmp.c $(C_DEPS)
$(BASE_CC) $(COMMON_CFLAGS) $(BASE_CFLAGS) $(OMP_CFLAGS) $^ $(COMMON_LDFLAGS) -o $@ $(BASE_CC) $(COMMON_CFLAGS) $(BASE_CFLAGS) $(OMP_CFLAGS) $^ $(COMMON_LDFLAGS) -o $@
ca_mpi_p2p: ca_mpi_p2p.c $(C_DEPS)
$(MPI_CC) $(COMMON_CFLAGS) $(BASE_CFLAGS) $(MPI_CFLAGS) $^ $(COMMON_LDFLAGS) -o $@
ca_mpi_p2p_hybrid: ca_mpi_p2p.c $(C_DEPS)
$(MPI_CC) $(COMMON_CFLAGS) $(BASE_CFLAGS) $(MPI_CFLAGS) $(OMP_CFLAGS) $^ $(COMMON_LDFLAGS) -o $@
.PHONY: test .PHONY: test
test: $(TARGETS) test: $(TARGETS)
...@@ -49,21 +34,6 @@ test: $(TARGETS) ...@@ -49,21 +34,6 @@ test: $(TARGETS)
done \ done \
done done
.PHONY: mpi-test
mpi-test: $(MPI_TARGETS)
@for ITS in 10 31 57 100; do \
for LINES in 20 33 47 100; do \
for NP in 2 3 4; do \
echo "$$LINES lines, $$ITS iterations, $$NP procs"; \
for BINARY in ca_seq $^; do \
printf '%-10s\t' $$BINARY; \
mpiexec -n $$NP ./$$BINARY $$LINES $$ITS; \
done \
done \
done \
done
.PHONY: bench .PHONY: bench
bench: ca_openmp bench: ca_openmp
......
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
#include "ca_common.h" #include "ca_common.h"
#include "random.h" #include "random.h"
#ifdef USE_MPI
#include <mpi.h>
#endif
/* determine random integer between 0 and n-1 */ /* determine random integer between 0 and n-1 */
#define randInt(n) ((int)(nextRandomLEcuyer() * n)) #define randInt(n) ((int)(nextRandomLEcuyer() * n))
...@@ -100,90 +96,3 @@ void ca_hash_and_report(line_t *buf, int lines, double time_in_s) ...@@ -100,90 +96,3 @@ void ca_hash_and_report(line_t *buf, int lines, double time_in_s)
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
} }
#ifdef MPI_VERSION /* defined by mpi.h */
static int num_remainder_procs;
#ifdef USE_MPI_TOPOLOGY
static MPI_Comm topo_comm;
#endif
void ca_mpi_init(int num_procs, int rank, int num_total_lines,
int *num_local_lines, int *global_first_line)
{
*num_local_lines = num_total_lines / num_procs;
*global_first_line = rank * (*num_local_lines);
/* if work cannot be distributed equally, distribute the remaining lines equally */
num_remainder_procs = num_total_lines % num_procs;
if (rank < num_remainder_procs) {
(*num_local_lines)++;
*global_first_line = *global_first_line + rank;
} else {
*global_first_line = *global_first_line + num_remainder_procs;
}
#ifdef USE_TOPO
int topo_periodic = 1, topo_dim = num_procs;
MPI_Cart_create(MPI_COMM_WORLD, 1, &topo_dim, &topo_periodic, 0, &topo_comm);
#endif
}
#define TAG_RESULT (0xCAFE)
void ca_mpi_hash_and_report(line_t* local_buf, int num_local_lines,
int num_total_lines, int num_procs, double time_in_s)
{
int i, rank, num_lines = num_local_lines, count;
uint32_t md_len;
uint8_t hash[MD5_DIGEST_LENGTH];
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
count = num_local_lines;
ca_clean_ghost_zones(local_buf + 1, num_local_lines);
/* insert our own data into MD5 hash */
EVP_DigestUpdate(ctx, local_buf + 1, num_local_lines * sizeof(line_t));
/* recieve partial results from all other processes in our local buffer and
* update the hash. Our buffer is garanteed to have the maximum required
* size in any case (see partioning above) */
for (i = 1; i < num_procs; i++) {
num_lines = num_total_lines / num_procs;
if (i < num_remainder_procs) {
num_lines++;
}
count += num_lines;
MPI_Recv(
local_buf, num_lines * LINE_SIZE, CA_MPI_CELL_DATATYPE,
i, TAG_RESULT, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
ca_clean_ghost_zones(local_buf, num_lines);
EVP_DigestUpdate(ctx, local_buf, num_lines * sizeof(line_t));
}
EVP_DigestFinal_ex(ctx, hash, &md_len);
char* hash_str = ca_buffer_to_hex_str(hash, MD5_DIGEST_LENGTH);
ca_print_hash_and_time(hash_str, time_in_s);
free(hash_str);
EVP_MD_CTX_free(ctx);
} else {
MPI_Send(
local_buf[1], num_local_lines * LINE_SIZE, CA_MPI_CELL_DATATYPE,
0, TAG_RESULT, MPI_COMM_WORLD);
}
#ifdef USE_MPI_TOPOLOGY
MPI_Comm_free(&topo_comm);
#endif
}
#endif /* MPI_VERSION */
...@@ -41,20 +41,4 @@ void ca_hash_and_report(line_t *buf, int lines, double time_in_s); ...@@ -41,20 +41,4 @@ void ca_hash_and_report(line_t *buf, int lines, double time_in_s);
} }
#endif #endif
#ifdef USE_MPI
/* next/prev process in communicator */
#define PREV_PROC(n, num_procs) ((n - 1 + num_procs) % num_procs)
#define SUCC_PROC(n, num_procs) ((n + 1) % num_procs)
#define CA_MPI_CELL_DATATYPE MPI_BYTE
void ca_mpi_init(int num_procs, int rank, int num_total_lines,
int *num_local_lines, int *global_first_line);
void ca_mpi_hash_and_report(line_t* local_buf, int num_local_lines,
int num_total_lines, int num_procs, double time_in_s);
#endif /* USE_MPI */
#endif /* CA_COMMON_H */ #endif /* CA_COMMON_H */
/*
* simulate a cellular automaton with periodic boundaries (torus-like)
* MPI version using two-sided blocking communication
*
* (c) 2016 Steffen Christgau (C99 port, modularization, parallelization)
* (c) 1996,1997 Peter Sanders, Ingo Boesnach (original source)
*
* command line arguments:
* #1: Number of lines
* #2: Number of iterations to be simulated
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#include "ca_common.h"
/* tags for communication */
#define TAG_SEND_UPPER_BOUND (1)
#define TAG_SEND_LOWER_BOUND (2)
#define TAG_RECV_UPPER_BOUND TAG_SEND_LOWER_BOUND
#define TAG_RECV_LOWER_BOUND TAG_SEND_UPPER_BOUND
/* --------------------- CA simulation -------------------------------- */
/* annealing rule from ChoDro96 page 34
* the table is used to map the number of nonzero
* states in the neighborhood to the new state
*/
static const cell_state_t anneal[10] = {0, 0, 0, 0, 1, 0, 1, 1, 1, 1};
/* treat torus like boundary conditions */
static void boundary(line_t *buf, int lines)
{
for (int y = 0; y <= lines + 1; y++) {
/* copy rightmost column to the buffer column 0 */
buf[y][0] = buf[y][XSIZE];
/* copy leftmost column to the buffer column XSIZE + 1 */
buf[y][XSIZE+1] = buf[y][1];
}
/* no wrap of upper/lower boundary, since it is done by exchanged ghost zones */
}
/* make one simulation iteration with lines lines.
* old configuration is in from, new one is written to to.
*/
static void simulate(line_t *from, line_t *to, int lines)
{
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int y = 1; y <= lines; y++) {
for (int x = 1; x <= XSIZE; x++) {
to[y][x] = transition(from, x, y);
}
}
}
/* --------------------- measurement ---------------------------------- */
int main(int argc, char** argv)
{
int num_total_lines, num_local_lines, num_skip_lines, its;
/* init MPI and application */
MPI_Init(&argc, &argv);
ca_init(argc, argv, &num_total_lines, &its);
int num_procs, local_rank;
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &local_rank);
ca_mpi_init(num_procs, local_rank, num_total_lines,
&num_local_lines, &num_skip_lines);
line_t *from = calloc((num_local_lines + 2), sizeof(*from));
line_t *to = calloc((num_local_lines + 2), sizeof(*to));
ca_init_config(from, num_local_lines, num_skip_lines);
/* actual computation */
TIME_GET(sim_start);
for (int i = 0; i < its; i++) {
MPI_Sendrecv(
from[1], LINE_SIZE, CA_MPI_CELL_DATATYPE,
PREV_PROC(local_rank, num_procs), TAG_SEND_UPPER_BOUND,
from[num_local_lines + 1], LINE_SIZE, CA_MPI_CELL_DATATYPE,
SUCC_PROC(local_rank, num_procs), TAG_RECV_LOWER_BOUND, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
MPI_Sendrecv(
from[num_local_lines], LINE_SIZE, CA_MPI_CELL_DATATYPE,
SUCC_PROC(local_rank, num_procs), TAG_SEND_LOWER_BOUND,
from[0], LINE_SIZE, CA_MPI_CELL_DATATYPE,
PREV_PROC(local_rank, num_procs), TAG_RECV_UPPER_BOUND, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
boundary(from, num_local_lines);
simulate(from, to, num_local_lines);
line_t *temp = from;
from = to;
to = temp;
}
TIME_GET(sim_stop);
ca_mpi_hash_and_report(from, num_local_lines, num_total_lines,
num_procs, TIME_DIFF(sim_start, sim_stop));
free(from);
free(to);
MPI_Finalize();
return EXIT_SUCCESS;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment