Skip to content

Commit 86fde7a

Browse files
author
Martin D. Weinberg
committed
Enable parallel reading from a Tipsy file
1 parent cb6c7c1 commit 86fde7a

File tree

1 file changed

+104
-26
lines changed

1 file changed

+104
-26
lines changed

include/tipsy.H

Lines changed: 104 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#ifndef _tipsy_H
22
#define _tipsy_H
33

4+
// For MPI awareness
5+
//
6+
#include <localmpi.H>
7+
8+
49
// Forward declare PR::Tipsy so it can friend TipsyFile
510
//
611
namespace PR {
@@ -157,24 +162,59 @@ namespace TipsyReader
157162
return header.nbodies;
158163
}
159164

165+
//! Generate stream position for parallel read
166+
//! \param nsize The number of particles to read
167+
//! \param ssize The size of each particle structure in bytes
168+
unsigned xdr_psize(int nsize, int ssize)
169+
{
170+
// Number of particles per process
171+
int psize = nsize/numprocs;
172+
173+
// Get current stream position
174+
auto pos = xdr_getpos(&xdrs);
175+
176+
// Move the stream position to the start of this process' data
177+
pos += psize * myid * ssize;
178+
if (xdr_setpos(&xdrs, pos) == 0) {
179+
throw std::runtime_error("TipsyFile: xdr_setpos failed");
180+
}
181+
182+
// If this is the last process, read the remainder
183+
if (myid == numprocs-1) psize = nsize - (numprocs-1)*psize;
184+
185+
return psize;
186+
}
187+
160188
int xdr_read()
161189
{
162190
int N=0;
163191

164192
if (header.nsph != 0) {
165-
gas_particles.resize(header.nsph);
193+
// Get the number of gas particles for this process
194+
auto psize = xdr_psize(header.nsph, sizeof(gas_particle));
195+
196+
// Do the read
197+
gas_particles.resize(psize);
166198
read_gas();
167199
N++;
168200
}
169201

170202
if (header.ndark != 0) {
171-
dark_particles.resize(header.ndark);
203+
// Get the number of dark particles for this process
204+
auto psize = xdr_psize(header.ndark, sizeof(dark_particle));
205+
206+
// Do the read
207+
dark_particles.resize(psize);
172208
read_dark();
173209
N++;
174210
}
175211

176212
if (header.nstar != 0) {
177-
star_particles.resize(header.nstar);
213+
// Get the number of star particles for this process
214+
auto psize = xdr_psize(header.nstar, sizeof(star_particle));
215+
216+
// Do the read
217+
star_particles.resize(psize);
178218
read_star();
179219
N++;
180220
}
@@ -186,7 +226,7 @@ namespace TipsyReader
186226
{
187227
if (sizeof(Real) == sizeof(float)) {
188228
xdr_vector(&xdrs, (char *) &gas_particles[0],
189-
header.nsph*(sizeof(gas_particle)/sizeof(Real)),
229+
gas_particles.size()*(sizeof(gas_particle)/sizeof(Real)),
190230
sizeof(Real), (xdrproc_t) xdr_float);
191231
}
192232
}
@@ -195,7 +235,7 @@ namespace TipsyReader
195235
{
196236
if (sizeof(Real) == sizeof(float)) {
197237
xdr_vector(&xdrs, (char *) &dark_particles[0],
198-
header.ndark*(sizeof(dark_particle)/sizeof(Real)),
238+
dark_particles.size()*(sizeof(dark_particle)/sizeof(Real)),
199239
sizeof(Real), (xdrproc_t) xdr_float);
200240
}
201241
}
@@ -204,7 +244,7 @@ namespace TipsyReader
204244
{
205245
if (sizeof(Real) == sizeof(float)) {
206246
xdr_vector(&xdrs, (char *) &star_particles[0],
207-
header.nstar*(sizeof(star_particle)/sizeof(Real)),
247+
star_particles.size()*(sizeof(star_particle)/sizeof(Real)),
208248
sizeof(Real), (xdrproc_t) xdr_float);
209249
}
210250
}
@@ -247,8 +287,9 @@ namespace TipsyReader
247287
try {
248288
input.read((char *)&header, sizeof(header));
249289
} catch (std::exception& e) {
250-
std::cerr << "TipsyFile native_header error: " << e.what() << std::endl;
251-
throw;
290+
std::ostringstream s;
291+
s << "TipsyFile native error reading header: " << e.what();
292+
throw std::runtime_error(s.str());
252293
}
253294
return 1;
254295
}
@@ -259,9 +300,10 @@ namespace TipsyReader
259300
input.open(filename);
260301
input.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
261302
} catch (std::exception& e) {
262-
std::cerr << "TipsyFile native error opening file <" << filename << ">, "
263-
<< e.what() << std::endl;
264-
throw;
303+
std::ostringstream s;
304+
s << "TipsyFile native error opening file <" << filename << ">: "
305+
<< e.what();
306+
throw std::runtime_error(s.str());
265307
}
266308

267309
if (native_header() != 1) {
@@ -271,24 +313,60 @@ namespace TipsyReader
271313
return header.nbodies;
272314
}
273315

316+
//! Generate stream position for parallel read
317+
//! \param nsize The number of particles to read
318+
//! \param ssize The size of each particle structure in bytes
319+
unsigned ios_psize(int nsize, int ssize)
320+
{
321+
// Number of particles per process
322+
int psize = nsize/numprocs;
323+
324+
// Get current stream position
325+
auto pos = input.tellg();
326+
327+
// Move the stream position to the start of this process' data
328+
pos += psize * myid * ssize;
329+
input.seekg(pos);
330+
if (input.fail()) {
331+
throw std::runtime_error("TipsyFile: seekg failed");
332+
}
333+
334+
// If this is the last process, read the remainder
335+
if (myid == numprocs-1) psize = nsize - (numprocs-1)*psize;
336+
337+
return psize;
338+
}
339+
274340
int native_read()
275341
{
276342
int N=0;
277343

278344
if (header.nsph != 0) {
279-
gas_particles.resize(header.nsph);
345+
// Get the number of gas particles for this process
346+
auto psize = ios_psize(header.nsph, sizeof(gas_particle));
347+
348+
// Do the read
349+
gas_particles.resize(psize);
280350
read_gas();
281351
N++;
282352
}
283353

284354
if (header.ndark != 0) {
285-
dark_particles.resize(header.ndark);
355+
// Get the number of dark particles for this process
356+
auto psize = ios_psize(header.ndark, sizeof(dark_particle));
357+
358+
// Do the read
359+
dark_particles.resize(psize);
286360
read_dark();
287361
N++;
288362
}
289363

290364
if (header.nstar != 0) {
291-
star_particles.resize(header.nstar);
365+
// Get the number of star particles for this process
366+
int psize = ios_psize(header.nstar, sizeof(star_particle));
367+
368+
// Do the read
369+
star_particles.resize(psize);
292370
read_star();
293371
N++;
294372
}
@@ -300,38 +378,38 @@ namespace TipsyReader
300378
{
301379
try {
302380
input.read((char *) &gas_particles[0],
303-
header.nsph*sizeof(gas_particle));
381+
gas_particles.size()*sizeof(gas_particle));
304382
}
305383
catch (std::exception& e) {
306-
std::cerr << "TipsyFile native error reading sph particles: "
307-
<< e.what() << std::endl;
308-
throw;
384+
std::ostringstream s;
385+
s << "TipsyFile native error reading gas particles: " << e.what();
386+
throw std::runtime_error(s.str());
309387
}
310388
}
311389

312390
void read_dark()
313391
{
314392
try {
315393
input.read((char *) &dark_particles[0],
316-
header.ndark*sizeof(dark_particle));
394+
dark_particles.size()*sizeof(dark_particle));
317395
}
318396
catch (std::exception& e) {
319-
std::cerr << "TipsyFile native error reading dark particles: "
320-
<< e.what() << std::endl;
321-
throw;
397+
std::ostringstream s;
398+
s << "TipsyFile native error reading dark particles: " << e.what();
399+
throw std::runtime_error(s.str());
322400
}
323401
}
324402

325403
void read_star()
326404
{
327405
try {
328406
input.read((char *) &star_particles[0],
329-
header.nstar*sizeof(star_particle));
407+
star_particles.size()*sizeof(star_particle));
330408
}
331409
catch (std::exception& e) {
332-
std::cerr << "TipsyFile native error reading star particles: "
333-
<< e.what() << std::endl;
334-
throw;
410+
std::ostringstream s;
411+
s << "TipsyFile native error reading star particles: " << e.what();
412+
throw std::runtime_error(s.str());
335413
}
336414
}
337415

0 commit comments

Comments
 (0)