Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
#include "configuration.h"
#include "mpitypes.h"
#include "io.h"
#include "world.h"
#include "simulation.h"
void broadcast_configuration(conf_t *c);
void read_input(const conf_t *c, world_t *world);
void iterate(const conf_t *c, world_t *world);
int main(int argc, char* argv[])
{
conf_t config;
world_t world;
MPI_Init(&argc, &argv);
// Parse command line arguments
conf_init_from_args(&config, argc, argv);
if(info_enabled(&config)) conf_print(&config, stdout);
// Read input file
read_input(&config, &world);
// Run simulation
iterate(&config, &world);
if(info_enabled(&config)) printf("Done.\n");
MPI_Finalize();
return EXIT_SUCCESS;
}
void read_input(const conf_t *c, world_t *world) {
int rank;
const int periods[2] = {0}; // non-periodic boundaries
const int allow_reorder = 1;
MPI_Comm cart_comm;
char input_filename[FILE_NAME_SZ];
MPI_File file;
size_t global_sizes[2];
size_t header_length;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// Determine input file name
snprintf(input_filename, sizeof(input_filename), "%s%s", c->file_basename, FILE_EXT);
if(info_enabled(c)) printf("Reading '%s'...\n\n", input_filename);
MPI_File_open(MPI_COMM_WORLD, input_filename, MPI_MODE_RDONLY, MPI_INFO_NULL, &file);
// Read header
file_read_header(file, global_sizes, &header_length);
if(info_enabled(c)) printf(
"Read header (%ld characters).\n"
"Global size: %ld x %ld\n\n",
header_length, global_sizes[0], global_sizes[1]
);
if(debug_enabled(c)) printf(
"%03d: Local tile: [%ld %ld) x [%ld %ld)\n", rank,
world->local_start[0], world->local_start[0]+world->local_size[0],
world->local_start[1], world->local_start[1]+world->local_size[1]
);
// Initialize cells (determine local tile, allocate memory)
MPI_Cart_create(MPI_COMM_WORLD, 2, c->nprocs, periods, allow_reorder, &cart_comm);
world_init(world, cart_comm, global_sizes);
// Collectively read cell data
file_read_world(file, world, header_length);
MPI_File_close(&file);
}
void iterate(const conf_t *c, world_t *world)
{
const size_t n_it = c->n_iterations;
const size_t n_gen = c->n_generations_per_iteration;
size_t i, g;
double total_time, sim_time = 0, io_time = 0;
char output_filename[FILE_NAME_SZ+8];
MPI_File file;
size_t header_length;
if(info_enabled(c)) printf(
"Running %d iterations with %ld generations per iteration.\n\n",
n_it, n_gen
);
total_time = -MPI_Wtime();
g = 0;
for(i = 1; i <= n_it; i++) {
// Run n_gen generations
sim_time -= MPI_Wtime();
do_simulation(world, n_gen); g += n_gen;
sim_time += MPI_Wtime();
// Determine output filename
snprintf(
output_filename, sizeof(output_filename),
"%s+%07ld%s",
c->file_basename, g, FILE_EXT
);
// Write output file
io_time -= MPI_Wtime();
MPI_File_open(
MPI_COMM_WORLD, output_filename,
MPI_MODE_CREATE | MPI_MODE_WRONLY,
MPI_INFO_NULL, &file
);
file_write_header(file, world, &header_length);
file_write_world(file, world, header_length);
MPI_File_close(&file);
io_time += MPI_Wtime();
if(info_enabled(c)) printf("Done iteration %-4d - Generation %-7ld - written '%s'.\n", i, g, output_filename);
}
total_time += MPI_Wtime();
if(info_enabled(c)) printf(
"\nStatistics:\n"
" * Generations per second: %.0f\n"
" * Net simulation time (s): %f\n"
" * Net I/O time (s): %f\n"
" * Total time (s): %f\n\n",
g / sim_time, sim_time, io_time, total_time
);
}