mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-04 23:31:12 +00:00
Imported libSDF into VOID tree
This commit is contained in:
parent
c6dd08bd7d
commit
2d09cb68df
55 changed files with 12667 additions and 0 deletions
106
external/libsdf/libmpmy/GNUmakefile
vendored
Normal file
106
external/libsdf/libmpmy/GNUmakefile
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
# Make.$(ARCH) sets many of the variables used below including:
|
||||
# CC, CFLAGS, AS, RANLIB, objdir, objsuf, asmdir
|
||||
|
||||
# This Makefile is 'non-standard' because we are trying to create a .o
|
||||
# file in the '$(libdir)' directory. Furthermore, the name of the
|
||||
# file we are creating can't be determined until after we have 'include'd
|
||||
# the $(ARCH)-specific makefile (so we can use the default PAROS).
|
||||
#
|
||||
# The dependencies are even more unreliable than usual.
|
||||
#
|
||||
# It's amazing that it works at all...
|
||||
|
||||
treedir=..
|
||||
treedir_sed=\.\.
|
||||
appexcludes=
|
||||
libname=NO_NAME
|
||||
# This is here only to allow 'make depends' to work.
|
||||
src=mpmy_seq.c mpmy_lsv.c mpmy_nx.c mpmy_vertex.c mpmy_sunmos.c mpmy_mpi.c mpmy_eui.c mpmy_pvm.c mpmy_craypvm.c
|
||||
|
||||
special_rule_for_all=YES
|
||||
all: special
|
||||
|
||||
include $(treedir)/Make-common/Make.$(ARCH)
|
||||
|
||||
include $(treedir)/Make-common/Make.generic
|
||||
|
||||
override CFLAGS:=$(PAROSCFLAGS) $(CFLAGS)
|
||||
|
||||
# I think these should be handled with PAROSCFLAGS
|
||||
# So sue me!
|
||||
#ifeq ($(PAROS),eui)
|
||||
#CFLAGS:=-I/usr/lpp/euih/eui $(CFLAGS)
|
||||
#endif
|
||||
|
||||
#ifeq ($(PAROS),mpi)
|
||||
#CFLAGS:=-I/usr/lpp/mpif $(CFLAGS)
|
||||
#endif
|
||||
|
||||
#ifeq ($(PAROS),srv)
|
||||
#CFLAGS:=-I$(SRVHOME)/include/cros3 $(CFLAGS)
|
||||
#endif
|
||||
|
||||
#ifeq ($(PAROS),pvm)
|
||||
#CFLAGS:=-I$(PVM_ROOT)/include $(CFLAGS)
|
||||
#endif
|
||||
|
||||
# order is important here. We need to make $(libdir)
|
||||
special: $(libdir)/mpmy_$(PAROS)$(objsuf)
|
||||
|
||||
$(libdir)/mpmy_$(PAROS)$(objsuf) : $(objdir)/mpmy_$(PAROS)$(objsuf) $(libdir)
|
||||
cp $< $@
|
||||
|
||||
$(objdir)/mpmy_$(PAROS)$(objsuf) : $(objdir)
|
||||
|
||||
# If there's a default PAROS for this architecture, then we put
|
||||
# mpmy_$(PAROS).o into libsw.a. To override it, it is
|
||||
# necessary to list mpmy_$(alternative).o AHEAD of libsw.a in the
|
||||
# link command. But if you just want the defaults (typically _seq), then
|
||||
# the only thing to link against is libsw.a.
|
||||
ifeq ($(PAROS),$(defaultPAROS))
|
||||
special: $(libdir)/libsw$(libext)($(objdir)/mpmy_$(PAROS)$(objsuf))
|
||||
$(RANLIB) $(libdir)/libsw$(libext)
|
||||
|
||||
$(libdir)/libsw$(libext)($(objdir)/mpmy_$(PAROS)$(objsuf)) : $(libdir)
|
||||
|
||||
endif
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
$(objdir)/mpmy_seq$(objsuf):
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Msgs.h
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/gccextensions.h $(treedir)/include/libsdf/mpmy.h
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/timers.h
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Assert.h $(treedir)/include/libsdf/error.h
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/mpmy_io.h $(treedir)/include/libsdf/mpmy_time.h
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/mpmy_abnormal.h timers_hwclock.c
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Malloc.h
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/chn.h mpmy_io.c
|
||||
$(objdir)/mpmy_seq$(objsuf):
|
||||
$(objdir)/mpmy_seq$(objsuf):
|
||||
$(objdir)/mpmy_seq$(objsuf):
|
||||
$(objdir)/mpmy_seq$(objsuf):
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/protos.h iozero.h
|
||||
$(objdir)/mpmy_seq$(objsuf): iozero.c io_generic.c mpmy_abnormal.c
|
||||
$(objdir)/mpmy_seq$(objsuf):
|
||||
$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/singlio.h
|
||||
$(objdir)/mpmy_seq$(objsuf): mpmy_generic.c
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_abnormal.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/gccextensions.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/Malloc.h $(treedir)/include/libsdf/error.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/chn.h $(treedir)/include/libsdf/Assert.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy.h $(treedir)/include/libsdf/timers.h
|
||||
$(objdir)/mpmy_mpi$(objsuf):
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/Msgs.h $(treedir)/include/libsdf/memfile.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): timers_hwclock.c
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_time.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): mpmy_mpiio.c
|
||||
$(objdir)/mpmy_mpi$(objsuf):
|
||||
$(objdir)/mpmy_mpi$(objsuf):
|
||||
$(objdir)/mpmy_mpi$(objsuf):
|
||||
$(objdir)/mpmy_mpi$(objsuf):
|
||||
$(objdir)/mpmy_mpi$(objsuf):
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/protos.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_io.h io_generic.c mpmy_abnormal.c
|
||||
$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/singlio.h
|
||||
$(objdir)/mpmy_mpi$(objsuf): mpmy_generic.c
|
59
external/libsdf/libmpmy/io_generic.c
vendored
Normal file
59
external/libsdf/libmpmy/io_generic.c
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Some i/o routines that are likely to be common... */
|
||||
|
||||
#ifndef HAVE_MPMY_FPRINTF
|
||||
|
||||
int MPMY_Fprintf(MPMYFile *fp, const char *fmt, ...){
|
||||
int ret;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = MPMY_Vfprintf(fp, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_VFPRINTF
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static char buf[1024];
|
||||
|
||||
int MPMY_Vfprintf(MPMYFile *fp, const char *fmt, va_list args){
|
||||
/* What a pain. Sometimes sprintf returns a char* and sometimes
|
||||
it returns an int. There's no good way to tell, but this
|
||||
should do.*/
|
||||
long ret = (long)vsprintf(buf, fmt, args);
|
||||
|
||||
/* Broken versions of sprintf return their first arg... */
|
||||
if( ret == (long)buf )
|
||||
ret = strlen(buf);
|
||||
|
||||
if( ret < 0 ){
|
||||
return ret;
|
||||
}
|
||||
if( ret >= sizeof(buf) ){
|
||||
/* This is serious. We've probably scribbled over memory.
|
||||
Maybe we should just bail out now?
|
||||
*/
|
||||
static int recursion;
|
||||
if( recursion++ == 0 )
|
||||
Error("MPMY_Vfprintf overflow. Data corruption likely!\n");
|
||||
recursion--;
|
||||
}
|
||||
|
||||
if( MPMY_Fwrite(buf, 1, ret, fp) != ret ){
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_FLUSH
|
||||
|
||||
/* This is here just for completeness... The higher levels all do
|
||||
their I/O using unbuffered primitives (read/write/open/close), so
|
||||
we don't have to do anything special to flush output */
|
||||
int MPMY_Fflush(MPMYFile *fp){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
360
external/libsdf/libmpmy/iozero.c
vendored
Normal file
360
external/libsdf/libmpmy/iozero.c
vendored
Normal file
|
@ -0,0 +1,360 @@
|
|||
/* More include madness. This is such good stuff, that I can't resist */
|
||||
/* just "#include"ing it into all the mpmy_??io.c files...*/
|
||||
|
||||
/* Try to use different tags for the different kinds of broadcasts... */
|
||||
#define BCAST_CLOSE 0x3579
|
||||
#define BCAST_OPEN 0x3779
|
||||
#define BCAST_READ1 0x3979
|
||||
#define BCAST_READ2 0x3b79
|
||||
#define BCAST_WRITE 0x3d79
|
||||
#define BCAST_LSEEK 0x3f79
|
||||
#define BCAST_TELL 0x4179
|
||||
#define BCAST_FLEN 0x4379
|
||||
#define BCAST_MKDIR 0x4579
|
||||
|
||||
static int
|
||||
open0(const char *path, int flags, int mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* paragon left the const out of the prototype */
|
||||
Msgf(("open0(path=%s, flags=%#x, mode=%#x\n", path, flags, mode));
|
||||
if (MPMY_Procnum() == 0){
|
||||
ret = open((char *)path, flags, mode);
|
||||
Msgf(("open returns %d on node 0\n", ret));
|
||||
}
|
||||
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_OPEN);
|
||||
Msgf(("open0 returning %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
close0(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (MPMY_Procnum() == 0) ret = close(fd);
|
||||
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_CLOSE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long
|
||||
read0(int fd, void *buf, unsigned long nbytes)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (MPMY_Procnum() == 0){
|
||||
ret = read(fd, buf, nbytes);
|
||||
Msgf(("read0: read(fd=%d, nbytes=%ld) returns %ld\n",
|
||||
fd, nbytes, ret));
|
||||
}
|
||||
MPMY_BcastTag(&ret, 1, MPMY_LONG, 0, BCAST_READ1);
|
||||
Msgf(("read0: after Bcast ret = %ld\n", ret));
|
||||
if( ret > 0 )
|
||||
MPMY_BcastTag(buf, ret, MPMY_CHAR, 0, BCAST_READ2);
|
||||
if( Msg_test(__FILE__)){
|
||||
int i;
|
||||
int sum = 0;
|
||||
char *cbuf = buf;
|
||||
for(i=0; i<ret; i++){
|
||||
sum ^= cbuf[i];
|
||||
}
|
||||
Msg_do("iozero: Fread(%ld), got %ld, sum=%d\n", nbytes, ret, sum);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static long
|
||||
write0(int fd, const void *buf, unsigned long nbytes)
|
||||
{
|
||||
long ret;
|
||||
|
||||
/* paragon left the const out of the prototype */
|
||||
if (MPMY_Procnum() == 0) ret = write(fd, (void *)buf, nbytes);
|
||||
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_WRITE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static off_t
|
||||
lseek0(int fd, off_t offset, int whence)
|
||||
{
|
||||
off_t ret;
|
||||
|
||||
if (MPMY_Procnum() == 0) ret = lseek(fd, offset, whence);
|
||||
MPMY_BcastTag(&ret, 1, MPMY_OFFT, 0, BCAST_LSEEK);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static off_t
|
||||
tell0(int fd)
|
||||
{
|
||||
off_t ret;
|
||||
|
||||
if (MPMY_Procnum() == 0) ret = lseek(fd, 0L, SEEK_CUR);
|
||||
MPMY_BcastTag(&ret, 1, MPMY_OFFT, 0, BCAST_TELL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static off_t
|
||||
flen(int fd)
|
||||
{
|
||||
off_t ret;
|
||||
|
||||
ret = lseek(fd, 0, SEEK_END);
|
||||
Msg_do("lseek on %d returns %ld, errno is %d\n", fd, ret, errno);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static off_t
|
||||
flen0(int fd)
|
||||
{
|
||||
off_t ret;
|
||||
|
||||
if (MPMY_Procnum() == 0) {
|
||||
ret = flen(fd);
|
||||
Msgf(("flen0 of %d returns %ld\n", fd, (long)ret));
|
||||
}
|
||||
MPMY_BcastTag(&ret, 1, MPMY_OFFT, 0, BCAST_FLEN);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mkdir0(const char *path, int mode){
|
||||
#if defined(__SUNMOS__) || defined(__AP1000__)
|
||||
return -1;
|
||||
#else
|
||||
int ret;
|
||||
if( MPMY_Procnum() == 0 ){
|
||||
ret = mkdir(path, mode);
|
||||
if( ret && errno == EEXIST ){
|
||||
/* Let's just pretend we really made it... */
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_MKDIR );
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static long
|
||||
fseekrd0(int fd, off_t offset, int whence, void *buf, int reclen,
|
||||
int nrecs)
|
||||
{
|
||||
int doseek;
|
||||
int real_whence;
|
||||
void *tmpbuf;
|
||||
int i;
|
||||
long nread;
|
||||
off_t len;
|
||||
struct {
|
||||
off_t offset;
|
||||
long whence;
|
||||
long reclen;
|
||||
long nrecs;
|
||||
} parbuf, *allbuf;
|
||||
|
||||
Msgf(("fseekrd0: (fd=%d, offset=%ld, whence=%d, buf=%p, reclen=%d, nrecs=%d)\n",
|
||||
fd, offset, whence, buf, reclen, nrecs));
|
||||
|
||||
parbuf.offset = offset;
|
||||
parbuf.whence = whence;
|
||||
parbuf.reclen = reclen;
|
||||
parbuf.nrecs = nrecs;
|
||||
|
||||
if (MPMY_Procnum() == 0) {
|
||||
allbuf = Malloc(sizeof(parbuf)*MPMY_Nproc());
|
||||
MPMY_Gather(&parbuf, sizeof(parbuf), MPMY_CHAR, allbuf,0);
|
||||
tmpbuf = Malloc(reclen*nrecs);
|
||||
for (i = 0; i < MPMY_Nproc(); i++) {
|
||||
offset = allbuf[i].offset;
|
||||
whence = allbuf[i].whence;
|
||||
reclen = allbuf[i].reclen;
|
||||
nrecs = allbuf[i].nrecs;
|
||||
|
||||
if( whence == MPMY_SEEK_CUR ){
|
||||
/* I'm not sure this is a well-defined operation */
|
||||
doseek = (offset != 0);
|
||||
}else if( whence == MPMY_SEEK_SET ){
|
||||
off_t cur_off = lseek(fd, 0, SEEK_CUR);
|
||||
if (cur_off < 0){
|
||||
static int issued_seek_warning;
|
||||
if( errno == ESPIPE ){
|
||||
if( !issued_seek_warning ){
|
||||
SeriousWarning("fseekrd: Can't seek on a pipe.\nAssuming the seek is a no-op. Good luck. You will not be warned again\n");
|
||||
issued_seek_warning = 1;
|
||||
}
|
||||
}else{
|
||||
Error("fseekrd: lseek(%d, 0, SEEK_CUR) failed, errno=%d\n",
|
||||
fd, errno);
|
||||
}
|
||||
doseek = 0;
|
||||
}else{
|
||||
doseek = (offset != cur_off);
|
||||
}
|
||||
}else{
|
||||
doseek = 1;
|
||||
}
|
||||
if( doseek ){
|
||||
switch(whence){
|
||||
case MPMY_SEEK_SET:
|
||||
real_whence = SEEK_SET;
|
||||
break;
|
||||
case MPMY_SEEK_CUR:
|
||||
real_whence = SEEK_CUR;
|
||||
break;
|
||||
case MPMY_SEEK_END:
|
||||
real_whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
Error("Illegal value of whence (%d) in fseekrd\n", whence);
|
||||
}
|
||||
if (lseek(fd, offset, real_whence) == -1L) {
|
||||
Error("fseekrd: cycle %d lseek(%d, %ld, %d) failed, errno=%d\n",
|
||||
i, fd, offset, whence, errno);
|
||||
}
|
||||
}
|
||||
len = 0;
|
||||
while (len < reclen*nrecs) {
|
||||
nread = read(fd, (char *)tmpbuf+len, reclen*nrecs-len);
|
||||
if (nread == -1) {
|
||||
Error("fseekrd: read(%d, %ld) failed, errno=%d\n",
|
||||
fd, reclen*nrecs-len, errno);
|
||||
} else if (nread == 0) {
|
||||
Error("fseekrd: read(%d, %ld) got EOF\n",
|
||||
fd, reclen*nrecs-len);
|
||||
} else {
|
||||
Msgf(("fseekrd: got %ld\n", nread));
|
||||
len += nread;
|
||||
}
|
||||
}
|
||||
if (len != reclen*nrecs) {
|
||||
Error("fseekrd: Wrong amount of data\n");
|
||||
}
|
||||
if (i) {
|
||||
MPMY_send(tmpbuf, reclen*nrecs, i, MPMY_IOTAG);
|
||||
} else {
|
||||
memcpy(buf, tmpbuf, reclen*nrecs);
|
||||
}
|
||||
}
|
||||
Free(tmpbuf);
|
||||
Free(allbuf);
|
||||
} else {
|
||||
MPMY_Gather(&parbuf, sizeof(parbuf)/sizeof(long), MPMY_LONG, NULL, 0);
|
||||
MPMY_recvn(buf, reclen*nrecs, 0, MPMY_IOTAG);
|
||||
}
|
||||
return parbuf.nrecs;
|
||||
}
|
||||
|
||||
#define MAX_IOBUF (64*1024*1024)
|
||||
|
||||
static long
|
||||
write0_multi(int fd, const void *buf, off_t nbytes)
|
||||
{
|
||||
long ret;
|
||||
off_t *sizes;
|
||||
int i, n, sync;
|
||||
char *tmpbuf = 0;
|
||||
off_t total_bytes;
|
||||
int nproc = MPMY_Nproc();
|
||||
int procnum = MPMY_Procnum();
|
||||
|
||||
MPMY_Combine(&nbytes, &total_bytes, 1, MPMY_OFFT, MPMY_SUM);
|
||||
Msgf(("write0_multi, nbytes is %ld, total_bytes is %ld\n", nbytes, total_bytes));
|
||||
/* If the total is small enough, we might as well concat it on proc 0 */
|
||||
if (total_bytes <= MAX_IOBUF) {
|
||||
MPMY_NGather(buf, nbytes, MPMY_CHAR, (void **)&tmpbuf, 0);
|
||||
if (procnum == 0) {
|
||||
ret = write(fd, tmpbuf, total_bytes);
|
||||
if (ret != total_bytes) Error("write failed, errno=%d\n", errno);
|
||||
Msgf(("write0 %ld (one block)\n", ret));
|
||||
Free(tmpbuf);
|
||||
}
|
||||
return nbytes;
|
||||
} else if (procnum == 0) {
|
||||
sizes = Malloc(sizeof(off_t)*nproc);
|
||||
MPMY_Gather(&nbytes, 1, MPMY_OFFT, sizes, 0);
|
||||
ret = 0;
|
||||
while (nbytes > 0) {
|
||||
off_t nwrite = (nbytes > MAX_IOBUF) ? MAX_IOBUF : nbytes;
|
||||
off_t wrote;
|
||||
wrote = write(fd, buf+ret, nwrite);
|
||||
if (wrote != nwrite) Shout("write failed, errno=%d\n", errno);
|
||||
ret += wrote;
|
||||
nbytes -= wrote;
|
||||
}
|
||||
Msgf(("write0 %ld\n", ret));
|
||||
if (nproc > 1) {
|
||||
tmpbuf = Malloc(nbytes);
|
||||
for (i = procnum+1; i < nproc; i++) {
|
||||
/* This could be double-buffered */
|
||||
tmpbuf = Realloc(tmpbuf, sizes[i]);
|
||||
/* Avoid deluge of messages by sync */
|
||||
MPMY_send(&sync, sizeof(int), i, MPMY_IOTAG);
|
||||
MPMY_recvn(tmpbuf, sizes[i], i, MPMY_IOTAG);
|
||||
n = write(fd, tmpbuf, sizes[i]);
|
||||
if (n != sizes[i]) Shout("write failed, errno=%d\n", errno);
|
||||
Msgf(("write%d %d\n", i, n));
|
||||
/* should we send errno as well? */
|
||||
MPMY_send(&n, sizeof(int), i, MPMY_IOTAG);
|
||||
}
|
||||
Free(tmpbuf);
|
||||
}
|
||||
Free(sizes);
|
||||
} else {
|
||||
MPMY_Gather(&nbytes, 1, MPMY_OFFT, NULL, 0);
|
||||
MPMY_recvn(&sync, sizeof(int), 0, MPMY_IOTAG);
|
||||
Msgf(("sending %ld bytes\n", nbytes));
|
||||
MPMY_send(buf, nbytes, 0, MPMY_IOTAG);
|
||||
MPMY_recvn(&ret, sizeof(int), 0, MPMY_IOTAG);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long
|
||||
read0_multi(int fd, void *buf, off_t nbytes)
|
||||
{
|
||||
int ret;
|
||||
off_t *sizes;
|
||||
int i, n;
|
||||
char *tmpbuf;
|
||||
int nproc = MPMY_Nproc();
|
||||
int procnum = MPMY_Procnum();
|
||||
|
||||
if (sizeof(off_t) != sizeof(long long)) {
|
||||
Error("Type problem in write0_multi\n");
|
||||
}
|
||||
if (procnum == 0) {
|
||||
sizes = Malloc(sizeof(off_t)*nproc);
|
||||
MPMY_Gather(&nbytes, 1, MPMY_OFFT, sizes, 0);
|
||||
ret = read(fd, buf, nbytes);
|
||||
if (ret != nbytes) Shout("read failed, errno=%d\n", errno);
|
||||
Msgf(("read0 %d\n", ret));
|
||||
if (nproc > 1) {
|
||||
tmpbuf = Malloc(nbytes);
|
||||
for (i = procnum+1; i < nproc; i++) {
|
||||
/* This could be double-buffered */
|
||||
tmpbuf = Realloc(tmpbuf, sizes[i]);
|
||||
n = read(fd, tmpbuf, sizes[i]);
|
||||
MPMY_send(tmpbuf, n, i, MPMY_IOTAG);
|
||||
if (n != sizes[i]) Shout("read failed, errno=%d\n", errno);
|
||||
Msgf(("read%d %d\n", i, n));
|
||||
}
|
||||
Free(tmpbuf);
|
||||
}
|
||||
Free(sizes);
|
||||
} else {
|
||||
MPMY_Status stat;
|
||||
MPMY_Comm_request req;
|
||||
|
||||
MPMY_Gather(&nbytes, 1, MPMY_OFFT, NULL, 0);
|
||||
MPMY_Irecv(buf, nbytes, 0, MPMY_IOTAG, &req);
|
||||
MPMY_Wait(req, &stat);
|
||||
ret = MPMY_Count(&stat);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
20
external/libsdf/libmpmy/iozero.h
vendored
Normal file
20
external/libsdf/libmpmy/iozero.h
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef IOzeroDOTh
|
||||
#define IOzeroDOTh
|
||||
|
||||
#define MPMY_IOTAG (0x183)
|
||||
#define IoZero(fp) (fp->flags & MPMY_IOZERO)
|
||||
|
||||
static int open0(const char *path, int flags, int mode);
|
||||
static int close0(int fd);
|
||||
static int mkdir0(const char *path, int mode);
|
||||
static long read0(int fd, void *buf, unsigned long nbytes);
|
||||
static long write0(int fd, const void *buf, unsigned long nbytes);
|
||||
static off_t lseek0(int fd, off_t offset, int whence);
|
||||
static off_t tell0(int fd);
|
||||
static off_t flen(int fd);
|
||||
static off_t flen0(int fd);
|
||||
static long fseekrd0(int fd, off_t offset, int whence, void *buf,
|
||||
int reclen, int nrecs);
|
||||
static long write0_multi(int fd, const void *buf, off_t nbytes);
|
||||
static long read0_multi(int fd, void *buf, off_t nbytes);
|
||||
#endif
|
2
external/libsdf/libmpmy/mpmy-private.h
vendored
Normal file
2
external/libsdf/libmpmy/mpmy-private.h
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
|
259
external/libsdf/libmpmy/mpmy_abnormal.c
vendored
Normal file
259
external/libsdf/libmpmy/mpmy_abnormal.c
vendored
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* Yet another attempt to rationalize the abnormal termination of
|
||||
parallel programs.
|
||||
|
||||
Issues to consider:
|
||||
- Do core files exist, and are they useful.
|
||||
- Do we need to chdir before dumping a core file.
|
||||
- Exactly how do we go about dumping a core file.
|
||||
- Do we want to do anything else before quitting.
|
||||
- Sometimes we get the most information when we just return
|
||||
from a signal handler (delta).
|
||||
- Parts will need to be over-ridden by mpmy_<paros>.c, but
|
||||
duplication of code should be minimized.
|
||||
- include files, values of signals, etc. are all wildly system
|
||||
specific.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include "singlio.h"
|
||||
#include "Msgs.h"
|
||||
#include "mpmy_abnormal.h"
|
||||
|
||||
#ifndef MPMY_ABORT
|
||||
void MPMY_Abort(void){
|
||||
MPMY_RaiseAbnormal(SIGABRT);
|
||||
MPMY_SystemAbort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _AIX
|
||||
/* dje says AIX dumps core fine, but the debuggers are confused by
|
||||
the signal handlers. Another way of achieving this might be
|
||||
to set absiglist and MPMY_HAVE_ABSIGLIST in the mpmy_paros.c file. */
|
||||
#define NO_SIGNALS
|
||||
#endif
|
||||
|
||||
#if !defined( HAVE_ABSIG_LIST ) && !defined(NO_SIGNALS)
|
||||
static int absiglist[]={
|
||||
#if 0 && defined(SIGABRT) /* ANSI */
|
||||
/* DO NOT TRAP SIGABRT! Just leave it completely alone. We studiously
|
||||
avoid calling abort in our code, so we should just let SIGABRT do its
|
||||
normal, unmodified thing. */
|
||||
SIGABRT,
|
||||
#endif
|
||||
#ifdef SIGFPE /* ANSI */
|
||||
SIGFPE,
|
||||
#endif
|
||||
#ifdef SIGIILL /* ANSI */
|
||||
SIGILL,
|
||||
#endif
|
||||
#ifdef SIGIOT /* ANSI */
|
||||
SIGIOT,
|
||||
#endif
|
||||
#ifdef SIGSEGV /* ANSI */
|
||||
SIGSEGV,
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
SIGQUIT,
|
||||
#endif
|
||||
#ifdef SIGTRAP
|
||||
SIGTRAP,
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
SIGEMT,
|
||||
#endif
|
||||
#ifdef SIGKILL
|
||||
SIGKILL, /* for form's sake */
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
SIGBUS,
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
SIGSYS,
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
SIGPIPE,
|
||||
#endif
|
||||
/* Do we need to worry about a trailing comma?? */
|
||||
};
|
||||
#endif /* HAVE_ABSIGLIST */
|
||||
|
||||
#ifndef HAVE_SETUP_ABSIGS
|
||||
void _MPMY_setup_absigs(void){
|
||||
int i;
|
||||
#if !defined(NO_SIGNALS)
|
||||
for(i=0; i< sizeof(absiglist)/sizeof(*absiglist); i++){
|
||||
signal(absiglist[i], MPMY_RaiseAbnormal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ABNORMAL
|
||||
#define MAXUSERFUNCS 64
|
||||
|
||||
static int nuserfuncs = 0;
|
||||
static Abhndlr userfuncs[MAXUSERFUNCS];
|
||||
/* Lots of functions are suitable for use as userfuncs to be called in
|
||||
the event of abnormal termination. These might include:
|
||||
malloc_print();
|
||||
PrintMemfile();
|
||||
PrintMPMYDiags();
|
||||
Msg_flush();
|
||||
MPMY_abchdir(); (with MPMY_abchdir_arg set beforehand)
|
||||
MPMY_SystemAbort();
|
||||
MPMY_SystemExit(); (with MPMY_exit_arg set beforehand)
|
||||
MPMY_Abannounce();
|
||||
|
||||
They are called in the reverse chronological order, so later functions
|
||||
might 'override' earlier ones. This isn't perfect, but it's better than
|
||||
the monolithic handler we had before.
|
||||
*/
|
||||
|
||||
void MPMY_OnAbnormal(Abhndlr hndlr){
|
||||
if(nuserfuncs < MAXUSERFUNCS)
|
||||
userfuncs[nuserfuncs++] = hndlr;
|
||||
}
|
||||
|
||||
int MPMY_Abnormal_signum;
|
||||
int MPMY_stop_abnormal_processing;
|
||||
void MPMY_RaiseAbnormal(int sig){
|
||||
int i;
|
||||
|
||||
MPMY_Abnormal_signum = sig;
|
||||
MPMY_stop_abnormal_processing = 0;
|
||||
/* Just cycle through the 'user' functions. */
|
||||
for(i=nuserfuncs-1; i>=0 && !MPMY_stop_abnormal_processing; i--){
|
||||
(*userfuncs[i])();
|
||||
}
|
||||
MPMY_Abnormal_signum = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYSTEM_ABORT
|
||||
void MPMY_SystemAbort(void){
|
||||
/* This should be unnecessary, since we didn't trap SIGABRT above. */
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYSTEM_EXIT
|
||||
int MPMY_exit_arg = 0;
|
||||
void MPMY_SystemExit(void){
|
||||
exit(MPMY_exit_arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_CHDIR
|
||||
/* This is pretty generic, but if the system can't even link against
|
||||
mkdir and chdir, then it will be necessary to override this with
|
||||
a noop in the PAROS-specific file. */
|
||||
#include <unistd.h>
|
||||
#ifndef __INTEL_SSD__ /* Intel's headers aren't safe for multiple inclusion! */
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
char MPMY_Abchdir_arg[128];
|
||||
|
||||
/* Suitable for use as a userfunc */
|
||||
void MPMY_Abchdir(void){
|
||||
if( strlen(MPMY_Abchdir_arg) ){
|
||||
errno=0;
|
||||
if( mkdir(MPMY_Abchdir_arg, 0777) && errno != EEXIST ){
|
||||
Msg_do("Can't mkdir(\"%s\"): %d\n", MPMY_Abchdir_arg, errno);
|
||||
}
|
||||
errno = 0;
|
||||
if( chdir(MPMY_Abchdir_arg) ){
|
||||
Msg_do("Can't chdir(\"%s\"): %d\n", MPMY_Abchdir_arg, errno);
|
||||
}else{
|
||||
Msg_do("New directory: \"%s\"\n", MPMY_Abchdir_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ABANNOUNCE
|
||||
void MPMY_Abannounce(void){
|
||||
static int announced;
|
||||
/* Don't repeat yourself! */
|
||||
if (!announced){
|
||||
Msg_do("MPMY_ABNORMAL_SIGNUM: %d\n", MPMY_Abnormal_signum);
|
||||
MPMY_Diagnostic(Msg_do);
|
||||
}
|
||||
Msg_flush();
|
||||
announced = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PRINTMPMY_DIAGS
|
||||
void PrintMPMYDiags(void){
|
||||
MPMY_Diagnostic(Msg_do);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_TIMEOUT
|
||||
/* Aieeee!!! Some systems can link alarm, but when the execute it,
|
||||
they die (cm5). Other systems can't even link it (sunmos, ap1000).
|
||||
Others will crash mysteriously if they use alarm (lsv). This isn't
|
||||
really a PAROS thing, and it's not really ARCH either. Aargh. */
|
||||
#ifdef CANT_USE_ALARM
|
||||
#define HAVE_MPMY_TIMEOUT
|
||||
void
|
||||
MPMY_TimeoutSet(int n){
|
||||
SinglWarning("Can't use alarm(). Timeout not set!\n");
|
||||
}
|
||||
|
||||
void
|
||||
MPMY_TimeoutReset(int n){
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
MPMY_TimeoutCancel(void){
|
||||
return;
|
||||
}
|
||||
|
||||
#else /* CANT_USE_ALARM */
|
||||
|
||||
static int nt;
|
||||
static void
|
||||
alrm_hndlr(int sig)
|
||||
{
|
||||
/* Should this be Shout followed by MPMY_RaiseAbnormal()?? */
|
||||
Error("Exceeded timeout (%d sec)\n", nt);
|
||||
}
|
||||
|
||||
void
|
||||
MPMY_TimeoutSet(int n)
|
||||
{
|
||||
void (*prev_sig)(int);
|
||||
prev_sig = signal(SIGALRM, alrm_hndlr);
|
||||
if( prev_sig == SIG_DFL || prev_sig == NULL || prev_sig == SIG_IGN ){
|
||||
singlPrintf("Setting timeout to %d seconds.\n", n);
|
||||
alarm(n);
|
||||
nt = n;
|
||||
}else{
|
||||
singlPrintf("There is already a handler for SIGALRM at %p\n",
|
||||
prev_sig);
|
||||
singlPrintf("NOT setting timeout!\n");
|
||||
signal(SIGALRM, prev_sig);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MPMY_TimeoutReset(int n)
|
||||
{
|
||||
alarm(n);
|
||||
nt = n;
|
||||
}
|
||||
|
||||
void
|
||||
MPMY_TimeoutCancel(void)
|
||||
{
|
||||
alarm(0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
}
|
||||
#endif /* CANT_USE_ALARM */
|
||||
#endif /* HAVE_MPMY_TIMEOUT */
|
286
external/libsdf/libmpmy/mpmy_generic.c
vendored
Normal file
286
external/libsdf/libmpmy/mpmy_generic.c
vendored
Normal file
|
@ -0,0 +1,286 @@
|
|||
/* This file is included in most (all?) of the mpmy_PAROS files.
|
||||
It defines several of the required mpmy functions in terms of a
|
||||
more primitive set. In some cases, however, there will be a PAROS
|
||||
specific way to achieve these results defined in the mpmy_PAROS file
|
||||
When that happens, the mpmy_PAROS file will also
|
||||
#define HAVE_MPMY_FUNCNAME
|
||||
so we know that we shouldn't define it here. */
|
||||
|
||||
/* These are set to the "right" thing on a uniprocessor, where it is
|
||||
most likely that we will neglect to call MPMY_Init, but where
|
||||
we really can proceed without any problems. I tried
|
||||
setting them to -1, but that just led to hard-to-understand
|
||||
crashes. We really should test occasionally that MPMY_Init has
|
||||
been called. But I'll leave that for another day... */
|
||||
int _MPMY_procnum_ = 0;
|
||||
int _MPMY_nproc_ = 1;
|
||||
int _MPMY_procs_per_node_ = 1;
|
||||
int _MPMY_initialized_ = 0;
|
||||
|
||||
Counter_t MPMYSendCnt;
|
||||
Counter_t MPMYRecvCnt;
|
||||
Counter_t MPMYDoneCnt;
|
||||
|
||||
#ifndef HAVE_MPMY_FLICK
|
||||
int MPMY_Flick(void){return MPMY_SUCCESS;}
|
||||
#endif /* HAVE_MPMY_FLICK */
|
||||
|
||||
#ifndef HAVE_MPMY_IRSEND
|
||||
int MPMY_Irsend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *req){
|
||||
return MPMY_Isend(buf, cnt, dest, tag, req);
|
||||
}
|
||||
#endif /* HAVE_MPMY_IRSEND */
|
||||
|
||||
#ifndef HAVE_MPMY_SHIFT
|
||||
/* An implementation of shift that just uses mpmy_isend/irecv */
|
||||
/* Some systems will have a better option, but this should always work. */
|
||||
|
||||
#define SHIFT_TAG 0x1492
|
||||
/* Because NX can't distinguish different sources when reading */
|
||||
/* messages, we help it out by adding processor info to the tag. */
|
||||
/* Is this really necessary for the "generic" implementation? */
|
||||
int MPMY_Shift(int proc, void *recvbuf, int recvcnt,
|
||||
const void *sendbuf, int sendcnt, MPMY_Status *stat){
|
||||
MPMY_Comm_request inreq, outreq;
|
||||
Msgf(("Starting MPMY_Shift(proc=%d, recvcnt=%d, sendcnt=%d:\n",
|
||||
proc, recvcnt, sendcnt));
|
||||
if (proc > _MPMY_procnum_) {
|
||||
MPMY_Irecv(recvbuf, recvcnt, proc, SHIFT_TAG+proc, &inreq);
|
||||
Msgf(("Irecv posted\n"));
|
||||
MPMY_Wait(inreq, stat);
|
||||
Msgf(("Irecv done\n"));
|
||||
MPMY_Isend(sendbuf, sendcnt, proc, SHIFT_TAG+MPMY_Procnum(), &outreq);
|
||||
Msgf(("Isend posted\n"));
|
||||
MPMY_Wait(outreq, NULL);
|
||||
Msgf(("Isend done\n"));
|
||||
} else {
|
||||
MPMY_Isend(sendbuf, sendcnt, proc, SHIFT_TAG+MPMY_Procnum(), &outreq);
|
||||
Msgf(("Isend posted\n"));
|
||||
MPMY_Wait(outreq, NULL);
|
||||
Msgf(("Isend done\n"));
|
||||
MPMY_Irecv(recvbuf, recvcnt, proc, SHIFT_TAG+proc, &inreq);
|
||||
Msgf(("Irecv posted\n"));
|
||||
MPMY_Wait(inreq, stat);
|
||||
Msgf(("Irecv done\n"));
|
||||
}
|
||||
|
||||
Msgf(("Finished MPMY_Shift\n"));
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
#endif /* HAVE_MPMY_SHIFT */
|
||||
|
||||
/*
|
||||
This could be smarter. In particular, it could recover gracefully
|
||||
from malloc failing to deliver.
|
||||
*/
|
||||
#ifndef HAVE_MPMY_SHIFT_OVERLAP
|
||||
#include "Malloc.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int MPMY_Shift_overlap(int proc, void *recvbuf, int recvcnt,
|
||||
const void *sendbuf, int sendcnt, MPMY_Status *stat){
|
||||
void *tmp = Malloc(sendcnt);
|
||||
int ret;
|
||||
|
||||
if( tmp == NULL && sendcnt>0 )
|
||||
return MPMY_FAILED;
|
||||
memcpy(tmp, sendbuf, sendcnt);
|
||||
ret = MPMY_Shift(proc, recvbuf, recvcnt, tmp, sendcnt, stat);
|
||||
Free(tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_MPMY_SHIFT_OVERLAP */
|
||||
|
||||
#ifndef HAVE_MPMY_SYNC
|
||||
/* Implementation of MPMY_Sync in terms of the 'combine' functions. */
|
||||
/* Some systems might provide a more useful interface. */
|
||||
|
||||
int MPMY_Sync(void){
|
||||
int junk=0;
|
||||
|
||||
/* I'm sure this is overkill! */
|
||||
return MPMY_Combine(&junk, &junk, 1, MPMY_INT, MPMY_BOR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_FINALIZE
|
||||
/* Any system specific stuff gets handled by a system-specific finalizer */
|
||||
int MPMY_Finalize(void){
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_WAIT
|
||||
/* An implementation of mpmy_wait that just busy-waits on MPMY_Test. */
|
||||
/* Some systems will have a better option, but this should always work. */
|
||||
|
||||
int MPMY_Wait(MPMY_Comm_request req, MPMY_Status *stat){
|
||||
/* Should we do a 'MPMY_Flick'' ? */
|
||||
int flag = 0;
|
||||
int ret;
|
||||
|
||||
do{
|
||||
MPMY_Flick();
|
||||
ret = MPMY_Test(req, &flag, stat);
|
||||
}while( ret == MPMY_SUCCESS && flag==0 );
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_MPMY_WAIT */
|
||||
|
||||
#ifndef HAVE_MPMY_WAIT2
|
||||
int MPMY_Wait2(MPMY_Comm_request req1, MPMY_Status *stat1,
|
||||
MPMY_Comm_request req2, MPMY_Status *stat2){
|
||||
/* Should we do a 'MPMY_Flick'' ? */
|
||||
int done1, done2;
|
||||
int ret;
|
||||
|
||||
done1 = done2 = 0;
|
||||
do{ /* loop until at least one is finished */
|
||||
MPMY_Flick();
|
||||
ret = MPMY_Test(req1, &done1, stat1);
|
||||
if( ret != MPMY_SUCCESS )
|
||||
return ret;
|
||||
ret = MPMY_Test(req2, &done2, stat2);
|
||||
if( ret != MPMY_SUCCESS )
|
||||
return ret;
|
||||
}while( done1 == 0 && done2 == 0 );
|
||||
|
||||
/* Now there's only one left, so we can call MPMY_Wait */
|
||||
if( !done1 ){
|
||||
ret = MPMY_Wait(req1, stat1);
|
||||
if( ret != MPMY_SUCCESS )
|
||||
return ret;
|
||||
}
|
||||
if( !done2 ){
|
||||
ret = MPMY_Wait(req2, stat2);
|
||||
if( ret != MPMY_SUCCESS )
|
||||
return ret;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_MPMY_DIAGNOSTIC
|
||||
void MPMY_Diagnostic(int (*printflike)(const char *, ...)){
|
||||
(*printflike)("No Diagnostic info for this MPMY\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_INITIALIZED
|
||||
int MPMY_Initialized(void){
|
||||
return _MPMY_initialized_;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_PHYSNODE
|
||||
const char *MPMY_Physnode(void){
|
||||
return "?";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MPMY_TIMERS
|
||||
/* This is a nightmare! Timers should really be ARCH dependent */
|
||||
/* but because of the CM5's special closeness to ARCH=sun4, they */
|
||||
/* are PAROS dependent, instead. That means that we would otherwise */
|
||||
/* repeat this code block in lots of mpmy_PAROS.c files */
|
||||
#ifdef _AIX
|
||||
/* No longer working?? Nov 3 1994
|
||||
# include "timers_readrtc.c" */
|
||||
#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME)
|
||||
#include "timers_posix.c"
|
||||
#endif
|
||||
/* it's not inconceivable to compile sequentially for the intels */
|
||||
/* However, we won't necessarily be linking against, e.g, hwclock
|
||||
#elif defined(__INTEL_SSD__)
|
||||
# include "timers_nx.c"
|
||||
*/
|
||||
#else
|
||||
#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME)
|
||||
# include "timers_posix.c"
|
||||
#endif
|
||||
#endif /* _AIX */
|
||||
#endif /* HAVE_MPMY_TIMERS */
|
||||
|
||||
static time_t job_start;
|
||||
static time_t job_end;
|
||||
static time_t checkpoint_last;
|
||||
static time_t checkpoint_next;
|
||||
static time_t checkpoint_interval;
|
||||
static int checkpoint_setup;
|
||||
|
||||
void
|
||||
MPMY_CheckpointSetup(int job_seconds, int interval_seconds, int step_seconds)
|
||||
{
|
||||
if (MPMY_Procnum() == 0) {
|
||||
job_start = time(NULL);
|
||||
if (job_seconds == -1) job_end = -1;
|
||||
else job_end = job_start + job_seconds - step_seconds;
|
||||
checkpoint_interval = interval_seconds - step_seconds;
|
||||
checkpoint_last = job_start;
|
||||
checkpoint_next = job_start + checkpoint_interval;
|
||||
Msg_do("Checkpoint Setup interval %ld start %ld next %ld end %ld\n",
|
||||
checkpoint_interval, job_start, checkpoint_next, job_end);
|
||||
}
|
||||
checkpoint_setup = 1;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_CheckpointDue(int next_output_seconds)
|
||||
{
|
||||
time_t t;
|
||||
int retval = 0;
|
||||
|
||||
if (MPMY_Procnum() == 0) {
|
||||
t = time(NULL);
|
||||
if (t >= checkpoint_next) retval = 1;
|
||||
if (next_output_seconds < checkpoint_interval/4) {
|
||||
Msg_do("Postponing checkpoint since output expected in %d seconds\n",
|
||||
next_output_seconds);
|
||||
retval = 0;
|
||||
}
|
||||
if (job_end > 0 && t >= job_end) retval = 1;
|
||||
}
|
||||
if (retval) Msg_do("Checkpoint Due\n");
|
||||
MPMY_Bcast(&retval, 1, MPMY_INT, 0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
MPMY_CheckpointFinished(void)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
if (MPMY_Procnum() == 0) {
|
||||
t = time(NULL);
|
||||
checkpoint_last = t;
|
||||
checkpoint_next = t + checkpoint_interval;
|
||||
if (job_end > 0 && checkpoint_next > job_end) checkpoint_next = job_end;
|
||||
Msg_do("next checkpoint %ld (%ld from now)\n", checkpoint_next, checkpoint_next-t);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_JobDone(void)
|
||||
{
|
||||
time_t t;
|
||||
int retval = 0;
|
||||
|
||||
if (MPMY_Procnum() == 0) {
|
||||
t = time(NULL);
|
||||
if (job_end > 0 && t >= job_end) {
|
||||
retval = 1;
|
||||
Msg_do("Job Done\n");
|
||||
}
|
||||
}
|
||||
MPMY_Bcast(&retval, 1, MPMY_INT, 0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifndef HAVE_MPMY_JOBREMAINING
|
||||
int
|
||||
MPMY_JobRemaining(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
525
external/libsdf/libmpmy/mpmy_io.c
vendored
Normal file
525
external/libsdf/libmpmy/mpmy_io.c
vendored
Normal file
|
@ -0,0 +1,525 @@
|
|||
|
||||
/* The default I/O model here is that only proc 0 can read/write etc. */
|
||||
/* There are two I/O modes for read and write, MULTI and SINGL */
|
||||
/* All other functions do not have an I/O mode associated with them */
|
||||
/* All calls must be loosely synchronous. There is a single file pointer */
|
||||
/* This model works on all machines, but it may not be the most efficient */
|
||||
|
||||
/* MPMY_NFILE extends the mpmy_io model to include multiple file segments */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Assert.h"
|
||||
#include "protos.h"
|
||||
#include "mpmy.h"
|
||||
#include "mpmy_io.h"
|
||||
#include "Msgs.h"
|
||||
#include "Malloc.h"
|
||||
#include "iozero.h"
|
||||
|
||||
#ifndef EINVAL
|
||||
/* just in case... */
|
||||
#define EINVAL 0
|
||||
#endif
|
||||
|
||||
#define NFILES 4096
|
||||
static struct _File{
|
||||
int fd;
|
||||
int iomode;
|
||||
int iotype;
|
||||
} _files[NFILES];
|
||||
|
||||
#define DEFAULT_PERMS 0644
|
||||
static int do_nfileio;
|
||||
|
||||
int
|
||||
MPMY_Nfileio(int val){
|
||||
int oldval = do_nfileio;
|
||||
do_nfileio = val;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_SetIOMode(MPMYFile *Fp, int iomode)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
|
||||
fp->iomode = iomode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MPMYFile *
|
||||
MPMY_Fopen(const char *path, int mpmy_flags)
|
||||
{
|
||||
int fd;
|
||||
int flags = 0;
|
||||
int iomode = MPMY_SINGL;
|
||||
int iotype = 0;
|
||||
|
||||
Msgf(("Fopen %s\n", path));
|
||||
if (mpmy_flags & MPMY_RDONLY) flags |= O_RDONLY;
|
||||
if (mpmy_flags & MPMY_WRONLY) flags |= O_WRONLY;
|
||||
if (mpmy_flags & MPMY_RDWR) flags |= O_RDWR;
|
||||
if (mpmy_flags & MPMY_APPEND) flags |= O_APPEND;
|
||||
if (mpmy_flags & MPMY_TRUNC) flags |= O_TRUNC;
|
||||
if (mpmy_flags & MPMY_CREAT) flags |= O_CREAT;
|
||||
|
||||
if (mpmy_flags & MPMY_MULTI) iomode = MPMY_MULTI;
|
||||
if (mpmy_flags & MPMY_SINGL) iomode = MPMY_SINGL;
|
||||
|
||||
/* This is a sub-mode which can work with either of the above */
|
||||
if (mpmy_flags & MPMY_NFILE) iotype = MPMY_NFILE;
|
||||
|
||||
if (mpmy_flags & MPMY_INDEPENDENT) {
|
||||
iotype = MPMY_INDEPENDENT;
|
||||
iomode = MPMY_MULTI;
|
||||
}
|
||||
|
||||
/* We need an external control for nfile mode */
|
||||
if (do_nfileio) iotype = MPMY_NFILE;
|
||||
|
||||
if (iotype == MPMY_NFILE) {
|
||||
char real_path[256];
|
||||
sprintf(real_path, "%s.p%03d", path, MPMY_Procnum());
|
||||
fd = open(real_path, flags, DEFAULT_PERMS);
|
||||
} else if (iotype == MPMY_INDEPENDENT) {
|
||||
fd = open(path, flags, DEFAULT_PERMS);
|
||||
} else {
|
||||
if( strcmp(path, "-") != 0 ){
|
||||
fd = open0(path, flags, DEFAULT_PERMS);
|
||||
}else{
|
||||
/* Be very afraid. */
|
||||
/* We made MPMY_RDONLY zero because O_RDONLY==0. But why
|
||||
did 'they' do that?! */
|
||||
if ( (mpmy_flags & MPMY_RDWR) )
|
||||
Error("Can't open '-' RDWR\n");
|
||||
#if MPMY_RDONLY != 0
|
||||
# error Aargh.
|
||||
#endif
|
||||
if(mpmy_flags & MPMY_WRONLY )
|
||||
fd = 1; /* stdout */
|
||||
else /* we can't test for MPMY_RDONLY! */
|
||||
fd = 0; /* stdout */
|
||||
}
|
||||
}
|
||||
|
||||
if (fd >= NFILES) Error("fd too large (%d)\n", fd);
|
||||
if(fd >= 0){
|
||||
_files[fd].iomode = iomode;
|
||||
_files[fd].iotype = iotype;
|
||||
_files[fd].fd = fd;
|
||||
Msgf(("Fopen returns %d, iomode=%d, flags=0x%x\n", fd, iomode, flags));
|
||||
return &(_files[fd]);
|
||||
}else{
|
||||
Msgf(("Fopen fails, errno=%d\n", errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fclose(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT) {
|
||||
ret = close(fp->fd);
|
||||
} else {
|
||||
ret = close0(fp->fd);
|
||||
}
|
||||
fp->fd = -1;
|
||||
Msgf(("Close returns %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Mkdir(const char *path, int mode){
|
||||
return mkdir0(path, mode);
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
ssize_t ret = -1;
|
||||
|
||||
Msgf(("Fread(ptr=%p, size=%ld, nitems=%ld, FILE=%p)\n",
|
||||
ptr, size, nitems, Fp));
|
||||
Msg_flush();
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (fp->iomode) {
|
||||
case MPMY_SINGL:
|
||||
ret = read0(fp->fd, ptr, (long)size*nitems);
|
||||
break;
|
||||
case MPMY_MULTI:
|
||||
if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT)
|
||||
ret = read(fp->fd, ptr, (long)size*nitems);
|
||||
else
|
||||
ret = read0_multi(fp->fd, ptr, (long)size*nitems);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
Msgf(("Fread returns %ld.\n", ret));
|
||||
if( ret < 0 ){
|
||||
Warning("MPMY_Fread: read returns %ld, errno=%d\n", ret, errno);
|
||||
return -1;
|
||||
}
|
||||
if (ret % size)
|
||||
Shout("MPMY_Fread has a problem, ret=%ld, size=%ld\n", ret, size);
|
||||
return ret/size;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (fp->iomode) {
|
||||
case MPMY_SINGL:
|
||||
ret = write0(fp->fd, ptr, size*nitems);
|
||||
break;
|
||||
case MPMY_MULTI:
|
||||
if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT)
|
||||
ret = write(fp->fd, ptr, size*nitems);
|
||||
else
|
||||
ret = write0_multi(fp->fd, ptr, size*nitems);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
Shout("Bad iomode in Fwrite\n");
|
||||
}
|
||||
|
||||
Msgf(("Fwrite returns %ld.\n", ret));
|
||||
if( ret < 0 ){
|
||||
Warning("MPMY_Fwrite: write returns %ld, errno=%d\n", ret, errno);
|
||||
return -1;
|
||||
}
|
||||
if (ret % size)
|
||||
Shout("MPMY_Fwrite has a problem: ret=%ld, size=%ld\n", ret, size);
|
||||
return ret/size;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
off_t ret;
|
||||
int real_whence = 0;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (whence == MPMY_SEEK_SET) real_whence = SEEK_SET;
|
||||
if (whence == MPMY_SEEK_CUR) real_whence = SEEK_CUR;
|
||||
if (whence == MPMY_SEEK_END) real_whence = SEEK_END;
|
||||
|
||||
if (fp->iotype == MPMY_INDEPENDENT) {
|
||||
ret = lseek(fp->fd, offset, real_whence);
|
||||
} else {
|
||||
ret = lseek0(fp->fd, offset, real_whence);
|
||||
}
|
||||
if (ret != -1) ret = 0;
|
||||
Msgf(("Fseek returns %ld\n", (long)ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Ftell(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
off_t ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iotype == MPMY_INDEPENDENT) {
|
||||
ret = lseek(fp->fd, 0L, SEEK_CUR);
|
||||
} else {
|
||||
ret = tell0(fp->fd);
|
||||
}
|
||||
Msgf(("Ftell returns %ld\n", (long)ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Flen(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
off_t ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iotype & MPMY_NFILE) {
|
||||
ret = flen(fp->fd);
|
||||
Msgf(("flen segment %ld\n", (long)ret));
|
||||
if (sizeof(ret) != sizeof(long)) {
|
||||
Error("Bad types in MPMY_Flen\n");
|
||||
}
|
||||
MPMY_Combine(&ret, &ret, 1, MPMY_LONG, MPMY_SUM);
|
||||
} else if (fp->iotype == MPMY_INDEPENDENT) {
|
||||
ret = flen(fp->fd);
|
||||
} else {
|
||||
ret = flen0(fp->fd);
|
||||
}
|
||||
Msgf(("Flen returns %ld\n", (long)ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAXREQ 4
|
||||
|
||||
static int
|
||||
fseekrd_nfile(int fd, off_t offset, int whence, void *buf, int reclen,
|
||||
int nrecs)
|
||||
{
|
||||
off_t offend;
|
||||
void *tmpbuf = 0; /* realloc null first time */
|
||||
int i;
|
||||
off_t nread;
|
||||
long size;
|
||||
struct {
|
||||
off_t offset;
|
||||
off_t flen;
|
||||
off_t start;
|
||||
long reclen;
|
||||
long nrecs;
|
||||
} parbuf, *allbuf;
|
||||
MPMY_Status stat;
|
||||
MPMY_Comm_request req[MAXREQ]; /* should be dynamic? */
|
||||
int nreq = 0;
|
||||
int procnum = MPMY_Procnum();
|
||||
off_t my_start, my_size, my_end;
|
||||
int nproc = MPMY_Nproc();
|
||||
|
||||
if (whence != MPMY_SEEK_SET)
|
||||
Error("Fseekrd Nfiles must use SEEK_SET\n");
|
||||
|
||||
parbuf.offset = offset;
|
||||
parbuf.reclen = reclen;
|
||||
parbuf.nrecs = nrecs;
|
||||
parbuf.flen = flen(fd);
|
||||
|
||||
allbuf = Malloc(sizeof(parbuf)*nproc);
|
||||
|
||||
MPMY_AllGather(&parbuf, sizeof(parbuf)/sizeof(long), MPMY_LONG, allbuf);
|
||||
|
||||
my_start = 0;
|
||||
for (i = 0; i < nproc; i++) {
|
||||
allbuf[i].start = my_start;
|
||||
my_start += allbuf[i].flen;
|
||||
}
|
||||
offend = offset+nrecs*reclen;
|
||||
my_start = allbuf[procnum].start;
|
||||
my_size = allbuf[procnum].flen;
|
||||
my_end = my_start+my_size;
|
||||
|
||||
Msgf(("reclen %d\n", reclen));
|
||||
Msgf(("offset %ld\n", offset));
|
||||
Msgf(("nrecs*reclen %d\n", nrecs*reclen));
|
||||
Msgf(("my_start %ld\n", my_start));
|
||||
Msgf(("my_size %ld\n", my_size));
|
||||
Msgf(("my_end %ld\n", my_end));
|
||||
|
||||
/* post Irecvs for my data */
|
||||
for (i = 0; i < nproc; i++) {
|
||||
if (allbuf[i].start<=offset && offset<allbuf[i].start+allbuf[i].flen) {
|
||||
size = allbuf[i].start+allbuf[i].flen-offset;
|
||||
if (size > reclen*nrecs) size = reclen*nrecs;
|
||||
Msgf(("irecv %ld from %d\n", size, i));
|
||||
if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n");
|
||||
MPMY_Irecv(buf, size, i, MPMY_IOTAG, &req[nreq]);
|
||||
++nreq;
|
||||
} else if (offset <= allbuf[i].start && offend > allbuf[i].start+allbuf[i].flen) {
|
||||
size = allbuf[i].flen;
|
||||
Msgf(("irecv %ld from %d\n", size, i));
|
||||
if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n");
|
||||
MPMY_Irecv((char *)buf+allbuf[i-1].start+allbuf[i-1].flen-offset,
|
||||
size, i, MPMY_IOTAG+2, &req[nreq]);
|
||||
++nreq;
|
||||
} else if (allbuf[i].start<offend && offend<=allbuf[i].start+allbuf[i].flen) {
|
||||
size = offend-allbuf[i].start;
|
||||
Msgf(("irecv %ld from %d\n", size, i));
|
||||
if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n");
|
||||
MPMY_Irecv((char *)buf+reclen*nrecs-size, size, i,
|
||||
MPMY_IOTAG+1, &req[nreq]);
|
||||
++nreq;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nproc; i++) {
|
||||
offset = allbuf[i].offset;
|
||||
reclen = allbuf[i].reclen;
|
||||
nrecs = allbuf[i].nrecs;
|
||||
offend = offset+reclen*nrecs;
|
||||
|
||||
if (my_start <= offset && offset < my_end) {
|
||||
size = my_end-offset;
|
||||
if (size > reclen*nrecs) size = reclen*nrecs;
|
||||
lseek(fd, offset-my_start, SEEK_SET);
|
||||
tmpbuf = Realloc(tmpbuf, size);
|
||||
nread = read(fd, tmpbuf, size);
|
||||
Msgf(("send %ld to %d\n", size, i));
|
||||
MPMY_send(tmpbuf, size, i, MPMY_IOTAG);
|
||||
} else if (offset <= my_start && offend > my_end) {
|
||||
size = my_end-my_start;
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
tmpbuf = Realloc(tmpbuf, size);
|
||||
nread = read(fd, tmpbuf, size);
|
||||
Msgf(("send %ld to %d\n", size, i));
|
||||
MPMY_send(tmpbuf, size, i, MPMY_IOTAG+2);
|
||||
} else if (my_start < offend && offend <= my_end) {
|
||||
size = offend-my_start;
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
tmpbuf = Realloc(tmpbuf, size);
|
||||
nread = read(fd, tmpbuf, size);
|
||||
Msgf(("send %ld to %d\n", size, i));
|
||||
MPMY_send(tmpbuf, size, i, MPMY_IOTAG+1);
|
||||
}
|
||||
}
|
||||
Free(tmpbuf);
|
||||
Free(allbuf);
|
||||
nread = 0;
|
||||
Msg_flush();
|
||||
#if 0
|
||||
for (i = 0; i < nreq; i++) {
|
||||
MPMY_Wait(req[i], &stat);
|
||||
Msgf(("Got %d from %d\n", stat.count, stat.src));
|
||||
nread += stat.count;
|
||||
}
|
||||
#else
|
||||
i = 0;
|
||||
while( nreq ){
|
||||
int done;
|
||||
/* Msgf(("Testing req[%d] = %p\n", i, req[i])); */
|
||||
MPMY_Test(req[i], &done, &stat);
|
||||
if( done ){
|
||||
Msgf(("Got %d from %d\n", stat.count, stat.src));
|
||||
nread += stat.count;
|
||||
Msgf(("Moving req[%d] = req[%d] = ", i, nreq-1));
|
||||
req[i] = req[--nreq];
|
||||
Msgf(("%p\n", req[i]));
|
||||
}else{
|
||||
/* Msgf(("Req[%d] not done yet\n", i)); */
|
||||
i++;
|
||||
}
|
||||
assert(i <= nreq );
|
||||
if( i == nreq )
|
||||
i = 0;
|
||||
}
|
||||
#endif
|
||||
Msgf(("fseekrd_nfile returning = %ld\n", nread/reclen));
|
||||
return nread/reclen;
|
||||
}
|
||||
|
||||
/* This should be called from fseekrd0 instead of replicating code */
|
||||
|
||||
static int
|
||||
fseekrd(int fd, off_t offset, int whence, void *buf, int reclen,
|
||||
int nrecs)
|
||||
{
|
||||
int doseek;
|
||||
int real_whence;
|
||||
off_t nread = 0;
|
||||
off_t len;
|
||||
|
||||
if( whence == SEEK_CUR ){
|
||||
doseek = (offset != 0);
|
||||
}else if( whence == SEEK_SET ){
|
||||
/* don't worry about errors. If ftell returns -1, */
|
||||
/* doseek will be turned on, and the fseek below will */
|
||||
/* (probably) fail */
|
||||
doseek = (lseek(fd, 0L, SEEK_CUR) != offset);
|
||||
}else{
|
||||
doseek = 1;
|
||||
}
|
||||
|
||||
if( doseek ){
|
||||
switch(whence){
|
||||
case MPMY_SEEK_SET:
|
||||
real_whence = SEEK_SET;
|
||||
break;
|
||||
case MPMY_SEEK_CUR:
|
||||
real_whence = SEEK_CUR;
|
||||
break;
|
||||
case MPMY_SEEK_END:
|
||||
real_whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
Shout("Illegal value of whence (%d) in fseekrd\n", whence);
|
||||
return -1;
|
||||
}
|
||||
if (lseek(fd, offset, real_whence) == -1) {
|
||||
Error("fseekrd: lseek(%d, %ld, %d) failed, errno=%d\n",
|
||||
fd, (long)offset, whence, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
len = 0;
|
||||
while (len < reclen*nrecs) {
|
||||
nread = read(fd, (char *)buf+len, reclen*nrecs-len);
|
||||
if (nread == -1) {
|
||||
Error("fseekrd: read(%d, %ld) failed, errno=%d\n",
|
||||
fd, (long)reclen*nrecs-len, errno);
|
||||
return -1;
|
||||
} else if (nread == 0) {
|
||||
Error("fseekrd: read(%d, %ld) got EOF\n",
|
||||
fd, (long)reclen*nrecs-len);
|
||||
return -1;
|
||||
} else {
|
||||
printf("%d fseekrd(%d): got %ld\n", fd, MPMY_Procnum(), (long)nread);
|
||||
len += nread;
|
||||
}
|
||||
}
|
||||
if (len != reclen*nrecs) Error("fseekrd: Wrong amount of data\n");
|
||||
return nread/reclen;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen,
|
||||
size_t nrecs)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iotype & MPMY_NFILE) {
|
||||
nrecs = fseekrd_nfile(fp->fd, offset, whence, buf, reclen, nrecs);
|
||||
} else if (fp->iotype == MPMY_INDEPENDENT) {
|
||||
nrecs = fseekrd(fp->fd, offset, whence, buf, reclen, nrecs);
|
||||
} else {
|
||||
nrecs = fseekrd0(fp->fd, offset, whence, buf, reclen, nrecs);
|
||||
}
|
||||
return nrecs;
|
||||
}
|
||||
|
||||
#include "iozero.c"
|
||||
#include "io_generic.c"
|
399
external/libsdf/libmpmy/mpmy_mpi.c
vendored
Normal file
399
external/libsdf/libmpmy/mpmy_mpi.c
vendored
Normal file
|
@ -0,0 +1,399 @@
|
|||
#ifdef _SWAMPI
|
||||
#include <swampi.h>
|
||||
#else
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
#include "mpmy_abnormal.h"
|
||||
|
||||
#include "Malloc.h"
|
||||
|
||||
#include "chn.h"
|
||||
#include "mpmy.h"
|
||||
#include "Assert.h"
|
||||
#include "timers.h"
|
||||
#include "Msgs.h"
|
||||
#include "error.h"
|
||||
#include "memfile.h"
|
||||
|
||||
struct comm_s {
|
||||
MPI_Request hndl;
|
||||
int inout;
|
||||
};
|
||||
|
||||
static Chn commchn;
|
||||
#define NCOMM 2048
|
||||
#define IN 1
|
||||
#define OUT 2
|
||||
|
||||
int MPMY_Isend(const void *buf, int cnt, int dest, int tag,
|
||||
MPMY_Comm_request *reqp) {
|
||||
struct comm_s *comm = ChnAlloc(&commchn);
|
||||
|
||||
Msgf(("Isend: buf=%p, cnt=%d, dest=%d, tag=%d\n",
|
||||
buf, cnt, dest, tag));
|
||||
if (MPI_Isend((void *)buf, cnt, MPI_BYTE, dest, tag, MPI_COMM_WORLD,
|
||||
&comm->hndl) != MPI_SUCCESS)
|
||||
Error("MPMY_Isend MPI_Isend failed\n");
|
||||
comm->inout = OUT;
|
||||
Msgf(("Isend: hndl=%ld\n", (long) comm->hndl));
|
||||
*reqp = comm;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define HAVE_MPMY_IRSEND
|
||||
int MPMY_Irsend(const void *buf, int cnt, int dest, int tag,
|
||||
MPMY_Comm_request *reqp) {
|
||||
struct comm_s *comm = ChnAlloc(&commchn);
|
||||
|
||||
Msgf(("Irsend: buf=%p, dest=%d, tag=%d\n",
|
||||
buf, dest, tag));
|
||||
if (MPI_Irsend(buf, cnt, MPI_BYTE, dest, tag, MPI_COMM_WORLD,
|
||||
&comm->hndl) != MPI_SUCCESS)
|
||||
Error("MPMY_Isend MPI_Irsend failed\n");
|
||||
comm->inout = OUT;
|
||||
Msgf(("Irsend: hndl=%d\n", (int) comm->hndl));
|
||||
*reqp = comm;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *reqp) {
|
||||
struct comm_s *comm = ChnAlloc(&commchn);
|
||||
|
||||
if (tag == MPMY_TAG_ANY) tag = MPI_ANY_TAG;
|
||||
if (src == MPMY_SOURCE_ANY) {
|
||||
src = MPI_ANY_SOURCE;
|
||||
} else if (src < 0 || src >= MPMY_Nproc()) {
|
||||
Error("Bad src (%d) in Irecv\n", src);
|
||||
}
|
||||
Msgf(("Irecv: buf=%p, src=%d, tag=%d\n",
|
||||
buf, src, tag));
|
||||
if (MPI_Irecv(buf, cnt, MPI_BYTE, src, tag, MPI_COMM_WORLD,
|
||||
&comm->hndl) != MPI_SUCCESS)
|
||||
Error("MPMY_Irecv MPI_Irecv failed\n");
|
||||
comm->inout = IN;
|
||||
Msgf(("Irecv: hndl=%ld\n", (long) comm->hndl));
|
||||
*reqp = comm;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_Test(MPMY_Comm_request req, int *flag, MPMY_Status *stat) {
|
||||
struct comm_s *comm = req;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
int ret = 0;
|
||||
|
||||
Msgf(("MPMY_Test hndl=%ld at %p\n", (long) comm->hndl, &comm->hndl));
|
||||
if ((ret = MPI_Test(&comm->hndl, flag, &status)) != MPI_SUCCESS) {
|
||||
Error("MPMY_Test MPI_Test failed (%d), MPI_ERROR %d, hndl=%ld at %p, flag=%p, status=%p\n",
|
||||
ret, status.MPI_ERROR, (long)comm->hndl, &comm->hndl, flag, &status);
|
||||
}
|
||||
Msgf(("Tested (%s), %d\n",
|
||||
(comm->inout==IN)?"in":"out", *flag));
|
||||
if (*flag) {
|
||||
if(comm->inout == IN) {
|
||||
MPI_Get_count(&status, MPI_BYTE, &cnt);
|
||||
Msgf(("Recvd(T) from %d, tag %d, count: %d\n",
|
||||
status.MPI_SOURCE, status.MPI_TAG, cnt));
|
||||
if (stat) {
|
||||
stat->src = status.MPI_SOURCE;
|
||||
stat->tag = status.MPI_TAG;
|
||||
stat->count = cnt;
|
||||
}
|
||||
}
|
||||
ChnFree(&commchn, comm);
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
#define HAVE_MPMY_WAIT
|
||||
int MPMY_Wait(MPMY_Comm_request req, MPMY_Status *stat) {
|
||||
struct comm_s *comm = req;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
|
||||
Msgf(("Wait for %ld\n", (long) comm->hndl));
|
||||
if (MPI_Wait(&comm->hndl, &status) != MPI_SUCCESS)
|
||||
Error("MPMY_Wait MPI_Wait failed\n");
|
||||
Msgf(("Waited for (%s), deallocated\n",
|
||||
(comm->inout==IN)?"in":"out"));
|
||||
if(comm->inout == IN) {
|
||||
MPI_Get_count(&status, MPI_BYTE, &cnt);
|
||||
Msgf(("Recvd(W) from %d, tag %d, count: %d\n",
|
||||
status.MPI_SOURCE, status.MPI_TAG, cnt));
|
||||
if (stat) {
|
||||
stat->src = status.MPI_SOURCE;
|
||||
stat->tag = status.MPI_TAG;
|
||||
stat->count = cnt;
|
||||
}
|
||||
}
|
||||
ChnFree(&commchn, comm);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
#define HAVE_MPMY_SHIFT
|
||||
#define SHIFT_TAG 0x1492
|
||||
int MPMY_Shift(int proc, void *recvbuf, int recvcnt,
|
||||
const void *sendbuf, int sendcnt, MPMY_Status *stat) {
|
||||
MPI_Status status;
|
||||
int count;
|
||||
|
||||
Msgf(("Starting MPMY_Shift(proc=%d, recvcnt=%d, sendcnt=%d, recvbuf=%p, sendbuf=%p\n",
|
||||
proc, recvcnt, sendcnt, recvbuf, sendbuf));
|
||||
|
||||
if (MPI_Sendrecv((void *)sendbuf, sendcnt, MPI_BYTE, proc, SHIFT_TAG,
|
||||
recvbuf, recvcnt, MPI_BYTE, proc, SHIFT_TAG,
|
||||
MPI_COMM_WORLD, &status) != MPI_SUCCESS)
|
||||
Error("MPMY_Shift MPI_Sendrecv failed\n");
|
||||
MPI_Get_count(&status, MPI_BYTE, &count);
|
||||
Msgf(("MPMY_Shift done, received=%d\n", count));
|
||||
if (stat) {
|
||||
stat->count = count;
|
||||
stat->src = status.MPI_SOURCE;
|
||||
stat->tag = status.MPI_TAG;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype,
|
||||
void *recvbuf, int recvcount, MPMY_Datatype recvtype)
|
||||
{
|
||||
MPI_Datatype st, rt;
|
||||
|
||||
switch (sendtype){
|
||||
case MPMY_FLOAT:
|
||||
st = MPI_FLOAT;
|
||||
break;
|
||||
case MPMY_DOUBLE:
|
||||
st = MPI_DOUBLE;
|
||||
break;
|
||||
case MPMY_INT:
|
||||
st = MPI_INT;
|
||||
break;
|
||||
case MPMY_CHAR:
|
||||
st = MPI_CHAR;
|
||||
break;
|
||||
default:
|
||||
Error("No type match in alltoall\n");
|
||||
}
|
||||
switch (recvtype){
|
||||
case MPMY_FLOAT:
|
||||
rt = MPI_FLOAT;
|
||||
break;
|
||||
case MPMY_DOUBLE:
|
||||
rt = MPI_DOUBLE;
|
||||
break;
|
||||
case MPMY_INT:
|
||||
rt = MPI_INT;
|
||||
break;
|
||||
case MPMY_CHAR:
|
||||
rt = MPI_CHAR;
|
||||
break;
|
||||
default:
|
||||
Error("No type match in alltoall\n");
|
||||
}
|
||||
MPI_Alltoall(sendbuf, sendcount, st,
|
||||
recvbuf, recvcount, rt, MPI_COMM_WORLD);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Alltoallv(void *sendbuf, int *sendcounts, int *sendoffsets, MPMY_Datatype sendtype,
|
||||
void *recvbuf, int *recvcounts, int *recvoffsets, MPMY_Datatype recvtype)
|
||||
{
|
||||
MPI_Datatype st, rt;
|
||||
|
||||
switch (sendtype){
|
||||
case MPMY_FLOAT:
|
||||
st = MPI_FLOAT;
|
||||
break;
|
||||
case MPMY_DOUBLE:
|
||||
st = MPI_DOUBLE;
|
||||
break;
|
||||
case MPMY_INT:
|
||||
st = MPI_INT;
|
||||
break;
|
||||
case MPMY_CHAR:
|
||||
st = MPI_CHAR;
|
||||
break;
|
||||
case MPMY_SHORT:
|
||||
st = MPI_SHORT;
|
||||
break;
|
||||
case MPMY_LONG:
|
||||
st = MPI_LONG;
|
||||
break;
|
||||
default:
|
||||
Error("No type match in alltoallv\n");
|
||||
}
|
||||
switch (recvtype){
|
||||
case MPMY_FLOAT:
|
||||
rt = MPI_FLOAT;
|
||||
break;
|
||||
case MPMY_DOUBLE:
|
||||
rt = MPI_DOUBLE;
|
||||
break;
|
||||
case MPMY_INT:
|
||||
rt = MPI_INT;
|
||||
break;
|
||||
case MPMY_CHAR:
|
||||
rt = MPI_CHAR;
|
||||
break;
|
||||
case MPMY_SHORT:
|
||||
rt = MPI_SHORT;
|
||||
break;
|
||||
case MPMY_LONG:
|
||||
rt = MPI_LONG;
|
||||
break;
|
||||
default:
|
||||
Error("No type match in alltoallv\n");
|
||||
}
|
||||
MPI_Alltoallv(sendbuf, sendcounts, sendoffsets, st,
|
||||
recvbuf, recvcounts, recvoffsets, rt, MPI_COMM_WORLD);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf)
|
||||
{
|
||||
MPI_Datatype st, rt;
|
||||
int recvcount = sendcount;
|
||||
|
||||
switch (type){
|
||||
case MPMY_FLOAT:
|
||||
st = MPI_FLOAT;
|
||||
break;
|
||||
case MPMY_DOUBLE:
|
||||
st = MPI_DOUBLE;
|
||||
break;
|
||||
case MPMY_INT:
|
||||
st = MPI_INT;
|
||||
break;
|
||||
case MPMY_CHAR:
|
||||
st = MPI_CHAR;
|
||||
break;
|
||||
case MPMY_SHORT:
|
||||
st = MPI_SHORT;
|
||||
break;
|
||||
case MPMY_LONG:
|
||||
st = MPI_LONG;
|
||||
break;
|
||||
default:
|
||||
Error("No type match in allgather\n");
|
||||
}
|
||||
rt = st;
|
||||
MPI_Allgather(sendbuf, sendcount, st,
|
||||
recvbuf, recvcount, rt, MPI_COMM_WORLD);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf,
|
||||
int *rcounts, int *roffsets)
|
||||
{
|
||||
MPI_Datatype st, rt;
|
||||
|
||||
switch (type){
|
||||
case MPMY_FLOAT:
|
||||
st = MPI_FLOAT;
|
||||
break;
|
||||
case MPMY_DOUBLE:
|
||||
st = MPI_DOUBLE;
|
||||
break;
|
||||
case MPMY_INT:
|
||||
st = MPI_INT;
|
||||
break;
|
||||
case MPMY_CHAR:
|
||||
st = MPI_CHAR;
|
||||
break;
|
||||
case MPMY_SHORT:
|
||||
st = MPI_SHORT;
|
||||
break;
|
||||
case MPMY_LONG:
|
||||
st = MPI_LONG;
|
||||
break;
|
||||
default:
|
||||
Error("No type match in allgather\n");
|
||||
}
|
||||
rt = st;
|
||||
MPI_Allgatherv(sendbuf, sendcount, st,
|
||||
recvbuf, rcounts, roffsets, rt, MPI_COMM_WORLD);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define HAVE_MPMY_SYNC
|
||||
int MPMY_Sync(void) {
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_Init(int *argcp, char ***argvp) {
|
||||
ChnInit(&commchn, sizeof(struct comm_s), NCOMM, Realloc_f);
|
||||
ChnMoreMem(&commchn); /* alloc now to prevent heap fragmentation later */
|
||||
if (MPI_Init(argcp, argvp) != MPI_SUCCESS)
|
||||
Error("MPMY_Init MPI_Init failed\n");
|
||||
if (MPI_Comm_size(MPI_COMM_WORLD, &_MPMY_nproc_) != MPI_SUCCESS)
|
||||
Error("MPMY_Init MPI_Comm_size failed\n");
|
||||
if (MPI_Comm_rank(MPI_COMM_WORLD, &_MPMY_procnum_) != MPI_SUCCESS)
|
||||
Error("MPMY_Init MPI_Comm_rank failed\n");
|
||||
#ifdef PROCS_PER_NODE
|
||||
_MPMY_procs_per_node_ = PROCS_PER_NODE;
|
||||
#else
|
||||
_MPMY_procs_per_node_ = 1;
|
||||
#endif
|
||||
_MPMY_setup_absigs();
|
||||
MPMY_OnAbnormal(MPMY_SystemAbort);
|
||||
MPMY_OnAbnormal(MPMY_Abannounce);
|
||||
MPMY_OnAbnormal(PrintMemfile);
|
||||
_MPMY_initialized_ = 1;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
#define HAVE_MPMY_FINALIZE
|
||||
int MPMY_Finalize(void){
|
||||
return (MPI_Finalize() == MPI_SUCCESS) ? MPMY_SUCCESS : MPMY_FAILED ;
|
||||
}
|
||||
|
||||
#define HAVE_MPMY_FLICK
|
||||
int MPMY_Flick(void){
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
#define HAVE_MPMY_JOBREMAINING
|
||||
int
|
||||
MPMY_JobRemaining(void)
|
||||
{
|
||||
/* returns -1 for failure, or if not a slurm job */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_HWCLOCK
|
||||
#include "timers_hwclock.c"
|
||||
#endif
|
||||
|
||||
#ifdef USE_GETTIME
|
||||
#include "timers_gettime.c"
|
||||
#endif
|
||||
|
||||
#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME)
|
||||
#define HAVE_MPMY_TIMERS
|
||||
#include "timers_mpi.c"
|
||||
#endif
|
||||
|
||||
#if defined(__CM5__) || defined(_AIX) || defined(__AP1000__)
|
||||
#define CANT_USE_ALARM
|
||||
#endif
|
||||
#if defined(__CM5__) || defined(__INTEL_SSD__)
|
||||
#include "mpmy_pario.c"
|
||||
#else
|
||||
#if defined(USE_MPIIO)
|
||||
#include "mpmy_mpiio.c"
|
||||
#else
|
||||
#include "mpmy_io.c"
|
||||
#endif
|
||||
#endif
|
||||
#include "mpmy_abnormal.c"
|
||||
#include "mpmy_generic.c"
|
292
external/libsdf/libmpmy/mpmy_mpiio.1.c
vendored
Normal file
292
external/libsdf/libmpmy/mpmy_mpiio.1.c
vendored
Normal file
|
@ -0,0 +1,292 @@
|
|||
/* This file contains the parallel I/O suitable for CMMD and NX.
|
||||
It wouldn't be hard to add cubix-syntax as well. Are there any
|
||||
other options? Would they fit in this structure? The only
|
||||
difference between CMMD and NX is in Fopen, where one
|
||||
system calls gopen() and the other calls CMMD_set_io_mode().
|
||||
We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide
|
||||
which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles,
|
||||
while __CM5__ is set by mpmy_cm5.c, which #includes this file.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mpi.h>
|
||||
#ifndef OPEN_MPI
|
||||
#include <mpio.h>
|
||||
#endif
|
||||
#include "protos.h"
|
||||
#include "mpmy.h"
|
||||
#include "mpmy_io.h"
|
||||
#include "Msgs.h"
|
||||
|
||||
#ifndef EINVAL
|
||||
/* just in case... */
|
||||
#define EINVAL 0
|
||||
#endif
|
||||
|
||||
#define NFILES 4096
|
||||
|
||||
static struct _File{
|
||||
MPI_File fd;
|
||||
int iomode;
|
||||
} _files[NFILES];
|
||||
|
||||
static int files; /* need dynamic storage */
|
||||
|
||||
static int do_nfileio;
|
||||
|
||||
MPMYFile *
|
||||
MPMY_Fopen(const char *path, int flags)
|
||||
{
|
||||
MPI_File fd;
|
||||
MPI_Info info;
|
||||
int iomode = MPMY_SINGL; /* default */
|
||||
int real_flags = MPI_MODE_RDONLY; /* if no flags specified */
|
||||
int ret;
|
||||
|
||||
Msgf(("Fopen %s, flags = 0x%x\n", path, flags));
|
||||
if (flags & MPMY_RDONLY) real_flags = MPI_MODE_RDONLY;
|
||||
if (flags & MPMY_WRONLY) real_flags = MPI_MODE_WRONLY;
|
||||
if (flags & MPMY_RDWR) real_flags = MPI_MODE_RDWR;
|
||||
if (flags & MPMY_APPEND) real_flags |= MPI_MODE_APPEND;
|
||||
if (flags & MPMY_TRUNC && ((flags & MPMY_WRONLY) || (flags & MPMY_RDWR))) {
|
||||
int fd;
|
||||
if (MPMY_Procnum() == 0) {
|
||||
fd = open(path, O_RDWR|O_TRUNC, 0644);
|
||||
if (fd < 0) Msgf(("Fopen fails, errno=%d\n", errno));
|
||||
else close(fd);
|
||||
MPMY_Sync();
|
||||
} else {
|
||||
MPMY_Sync();
|
||||
}
|
||||
}
|
||||
if (flags & MPMY_CREAT) real_flags |= MPI_MODE_CREATE;
|
||||
|
||||
/* Panasas optimizations */
|
||||
real_flags |= MPI_MODE_UNIQUE_OPEN; /* dangerous? */
|
||||
MPI_Info_create(&info);
|
||||
MPI_Info_set(info, "panfs_concurrent_write", "1");
|
||||
|
||||
/* Should we make sure that only one of them is on?? */
|
||||
if (flags & MPMY_MULTI) iomode = MPMY_MULTI;
|
||||
if (flags & MPMY_SINGL) iomode = MPMY_SINGL;
|
||||
|
||||
if (flags & MPMY_NFILE) Error("MPMY_NFILE not supported\n");
|
||||
if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n");
|
||||
if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n");
|
||||
|
||||
if (flags & MPMY_SINGL) {
|
||||
Msgf(("Fopen %s in SINGL mode\n", path));
|
||||
} else {
|
||||
Msgf(("Fopen %s in MULTI mode\n", path));
|
||||
}
|
||||
Msgf(("MPI_File_open %s with flags = 0x%x\n", path, real_flags));
|
||||
ret = MPI_File_open(MPI_COMM_WORLD, (char *)path, real_flags, info, &fd);
|
||||
|
||||
if (files >= NFILES) Error("files too large\n");
|
||||
if (ret == 0) {
|
||||
_files[files].iomode = iomode;
|
||||
_files[files].fd = fd;
|
||||
Msgf(("Fopen returns fd %p, iomode=%d, flags=0x%x\n",
|
||||
fd, iomode, flags));
|
||||
return &(_files[files++]);
|
||||
} else {
|
||||
Msgf(("Fopen fails, errno=%d\n", errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Nfileio(int val){
|
||||
int oldval = do_nfileio;
|
||||
do_nfileio = val;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fclose(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
Msgf(("Fclose %p\n", fp->fd));
|
||||
ret = MPI_File_close(&fp->fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Mkdir(const char *path, int mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( MPMY_Procnum() == 0 ){
|
||||
ret = mkdir(path, mode);
|
||||
if( ret && errno == EEXIST ){
|
||||
/* Let's just pretend we really made it... */
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, 0x4579 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
size_t nread = size*nitems;
|
||||
const char *p = ptr;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_read_all(fp->fd, (void *)p, nread, MPI_CHAR, &status);
|
||||
} else {
|
||||
MPI_File_read_ordered(fp->fd, (void *)p, nread, MPI_CHAR, &status);
|
||||
}
|
||||
MPI_Get_count(&status, MPI_BYTE, &cnt);
|
||||
if (cnt != nread) Error("MPMY_Fread has a problem\n");
|
||||
Msgf(("MPI_File_read from %p returns %d\n", fp->fd, cnt));
|
||||
return nitems;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
size_t nwrite = size*nitems;
|
||||
const char *p = ptr;
|
||||
|
||||
Msgf(("MPMY_Fwrite %ld %ld\n", size, nitems));
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_write_all(fp->fd, (void *)p, nwrite, MPI_CHAR, &status);
|
||||
} else {
|
||||
MPI_File_write_ordered(fp->fd, (void *)p, nwrite, MPI_CHAR, &status);
|
||||
}
|
||||
MPI_Get_count(&status, MPI_BYTE, &cnt);
|
||||
if (cnt != nwrite) Error("MPMY_Fread has a problem\n");
|
||||
Msgf(("MPI_File_write from %p returns %d\n", fp->fd, cnt));
|
||||
return nitems;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
MPI_Offset mpi_offset;
|
||||
int real_whence = 0;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (whence == MPMY_SEEK_SET) real_whence = MPI_SEEK_SET;
|
||||
if (whence == MPMY_SEEK_CUR) real_whence = MPI_SEEK_CUR;
|
||||
if (whence == MPMY_SEEK_END) real_whence = MPI_SEEK_END;
|
||||
|
||||
mpi_offset = offset; /* potential conversion problem */
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
ret = MPI_File_seek_shared(fp->fd, mpi_offset, real_whence);
|
||||
} else {
|
||||
ret = MPI_File_seek(fp->fd, mpi_offset, real_whence);
|
||||
}
|
||||
if (ret != -1) ret = 0;
|
||||
Msgf(("Fseek to %ld returns %d\n", (long)mpi_offset, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Ftell(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Offset mpi_offset;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_get_position_shared(fp->fd, &mpi_offset);
|
||||
} else {
|
||||
MPI_File_get_position(fp->fd, &mpi_offset);
|
||||
}
|
||||
Msgf(("Ftell returns %ld\n", (long)mpi_offset));
|
||||
return mpi_offset;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Flen(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Offset mpi_offset_current, mpi_offset_end;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_get_position_shared(fp->fd, &mpi_offset_current);
|
||||
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_END);
|
||||
MPI_File_get_position_shared(fp->fd, &mpi_offset_end);
|
||||
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_SET);
|
||||
} else {
|
||||
MPI_File_get_position(fp->fd, &mpi_offset_current);
|
||||
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_END);
|
||||
MPI_File_get_position(fp->fd, &mpi_offset_end);
|
||||
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_SET);
|
||||
}
|
||||
Msgf(("Flen returns %ld\n", (long)mpi_offset_end));
|
||||
return mpi_offset_end;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen,
|
||||
size_t nrecs)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Offset mpi_offset;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
size_t nread = reclen*nrecs;
|
||||
const char *p = buf;
|
||||
|
||||
Msgf(("Fseekrd %ld at %ld\n", (size_t)reclen*nrecs, offset));
|
||||
mpi_offset = offset;
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_read_at_all(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
|
||||
} else {
|
||||
MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
|
||||
}
|
||||
MPI_Get_count(&status, MPI_BYTE, &cnt);
|
||||
if (cnt != nread) Error("MPMY_Fseekrd has a problem, got %d expected %ld\n",
|
||||
cnt, nread);
|
||||
return nrecs;
|
||||
}
|
||||
|
||||
#include "io_generic.c"
|
346
external/libsdf/libmpmy/mpmy_mpiio.c
vendored
Normal file
346
external/libsdf/libmpmy/mpmy_mpiio.c
vendored
Normal file
|
@ -0,0 +1,346 @@
|
|||
/* This file contains the parallel I/O suitable for CMMD and NX.
|
||||
It wouldn't be hard to add cubix-syntax as well. Are there any
|
||||
other options? Would they fit in this structure? The only
|
||||
difference between CMMD and NX is in Fopen, where one
|
||||
system calls gopen() and the other calls CMMD_set_io_mode().
|
||||
We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide
|
||||
which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles,
|
||||
while __CM5__ is set by mpmy_cm5.c, which #includes this file.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mpi.h>
|
||||
#ifndef OPEN_MPI
|
||||
#include <mpio.h>
|
||||
#endif
|
||||
#include "protos.h"
|
||||
#include "mpmy.h"
|
||||
#include "mpmy_io.h"
|
||||
#include "Msgs.h"
|
||||
|
||||
#ifndef EINVAL
|
||||
/* just in case... */
|
||||
#define EINVAL 0
|
||||
#endif
|
||||
|
||||
#define NFILES 4096
|
||||
|
||||
/* MPI only allows 2GB buffer sizes, and MPI_Get_Count uses an int */
|
||||
#define MAXIOSIZE (256*1024*1024)
|
||||
|
||||
static struct _File{
|
||||
MPI_File fd;
|
||||
int iomode;
|
||||
} _files[NFILES];
|
||||
|
||||
static int files; /* need dynamic storage */
|
||||
|
||||
static int do_nfileio;
|
||||
|
||||
MPMYFile *
|
||||
MPMY_Fopen(const char *path, int flags)
|
||||
{
|
||||
MPI_File fd;
|
||||
MPI_Info info;
|
||||
int iomode = MPMY_SINGL; /* default */
|
||||
int real_flags = MPI_MODE_RDONLY; /* if no flags specified */
|
||||
int ret;
|
||||
|
||||
Msgf(("Fopen %s, flags = 0x%x\n", path, flags));
|
||||
if (flags & MPMY_RDONLY) real_flags = MPI_MODE_RDONLY;
|
||||
if (flags & MPMY_WRONLY) real_flags = MPI_MODE_WRONLY;
|
||||
if (flags & MPMY_RDWR) real_flags = MPI_MODE_RDWR;
|
||||
if (flags & MPMY_APPEND) real_flags |= MPI_MODE_APPEND;
|
||||
if (flags & MPMY_TRUNC && ((flags & MPMY_WRONLY) || (flags & MPMY_RDWR))) {
|
||||
int fd;
|
||||
if (MPMY_Procnum() == 0) {
|
||||
fd = open(path, O_RDWR|O_TRUNC, 0644);
|
||||
if (fd < 0) Msgf(("Fopen fails, errno=%d\n", errno));
|
||||
else close(fd);
|
||||
MPMY_Sync();
|
||||
} else {
|
||||
MPMY_Sync();
|
||||
}
|
||||
}
|
||||
if (flags & MPMY_CREAT) real_flags |= MPI_MODE_CREATE;
|
||||
|
||||
/* Panasas optimizations */
|
||||
if (!(flags & MPMY_RDONLY))
|
||||
real_flags |= MPI_MODE_UNIQUE_OPEN; /* dangerous? */
|
||||
MPI_Info_create(&info);
|
||||
MPI_Info_set(info, "panfs_concurrent_write", "1");
|
||||
|
||||
/* Should we make sure that only one of them is on?? */
|
||||
if (flags & MPMY_MULTI) iomode = MPMY_MULTI;
|
||||
if (flags & MPMY_SINGL) iomode = MPMY_SINGL;
|
||||
|
||||
if (flags & MPMY_NFILE) Error("MPMY_NFILE not supported\n");
|
||||
if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n");
|
||||
if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n");
|
||||
|
||||
if (flags & MPMY_SINGL) {
|
||||
Msgf(("Fopen %s in SINGL mode\n", path));
|
||||
} else {
|
||||
Msgf(("Fopen %s in MULTI mode\n", path));
|
||||
}
|
||||
Msgf(("MPI_File_open %s with flags = 0x%x\n", path, real_flags));
|
||||
ret = MPI_File_open(MPI_COMM_WORLD, (char *)path, real_flags, info, &fd);
|
||||
|
||||
if (files >= NFILES) Error("files too large\n");
|
||||
if (ret == 0) {
|
||||
_files[files].iomode = iomode;
|
||||
_files[files].fd = fd;
|
||||
Msgf(("Fopen returns fd %p, iomode=%d, flags=0x%x\n",
|
||||
fd, iomode, flags));
|
||||
return &(_files[files++]);
|
||||
} else {
|
||||
Msgf(("Fopen fails, errno=%d\n", errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Nfileio(int val){
|
||||
int oldval = do_nfileio;
|
||||
do_nfileio = val;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fclose(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
Msgf(("Fclose %p\n", fp->fd));
|
||||
ret = MPI_File_close(&fp->fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Mkdir(const char *path, int mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( MPMY_Procnum() == 0 ){
|
||||
ret = mkdir(path, mode);
|
||||
if( ret && errno == EEXIST ){
|
||||
/* Let's just pretend we really made it... */
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
MPMY_BcastTag(&ret, 1, MPMY_INT, 0, 0x4579 );
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
size_t nread = size*nitems;
|
||||
const char *p = ptr;
|
||||
|
||||
Msgf(("MPMY_Fread %ld %ld\n", size, nitems));
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
if (nread >= (1 << 31)) Error("MPMY_SINGL does not yet support large reads\n");
|
||||
MPI_File_read_all(fp->fd, (void *)p, nread, MPI_CHAR, &status);
|
||||
MPI_Get_count(&status, MPI_CHAR, &cnt);
|
||||
} else {
|
||||
MPI_Offset mpi_offset;
|
||||
size_t left, *sizes;
|
||||
int i;
|
||||
assert(sizeof(size_t) == MPMY_Datasize[MPMY_LONG]);
|
||||
sizes = Malloc(sizeof(size_t)*MPMY_Nproc());
|
||||
/* Use scan instead? */
|
||||
Native_MPMY_Allgather(&nread, 1, MPMY_LONG, sizes);
|
||||
MPI_File_get_position(fp->fd, &mpi_offset);
|
||||
Msgf(("Starting offset in MPMY_Fread is %lld\n", mpi_offset));
|
||||
for (i = 0; i < MPMY_Procnum(); i++) {
|
||||
mpi_offset += sizes[i];
|
||||
}
|
||||
Msgf(("My offset in MPMY_Fread is %lld\n", mpi_offset));
|
||||
Free(sizes);
|
||||
left = nread;
|
||||
while (left > 0) {
|
||||
nread = (left < MAXIOSIZE) ? left : MAXIOSIZE;
|
||||
Msgf(("read %ld at %lld\n", nread, mpi_offset));
|
||||
Msg_flush();
|
||||
MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_CHAR, &status);
|
||||
left -= nread;
|
||||
p += nread;
|
||||
mpi_offset += nread;
|
||||
MPI_Get_count(&status, MPI_CHAR, &cnt);
|
||||
}
|
||||
}
|
||||
return cnt/size;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
size_t nwrite = size*nitems;
|
||||
const char *p = ptr;
|
||||
|
||||
Msgf(("MPMY_Fwrite %ld %ld\n", size, nitems));
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
if (nwrite >= (1 << 31)) Error("MPMY_SINGL does not yet support large writes\n");
|
||||
MPI_File_write_all(fp->fd, (void *)p, nwrite, MPI_CHAR, &status);
|
||||
MPI_Get_count(&status, MPI_CHAR, &cnt);
|
||||
if (cnt != nwrite) Error("MPMY_Fwrite has a problem, wrote %d of %ld\n",
|
||||
cnt, nwrite);
|
||||
} else {
|
||||
MPI_Offset mpi_offset;
|
||||
size_t left, *sizes;
|
||||
int i;
|
||||
assert(sizeof(size_t) == MPMY_Datasize[MPMY_LONG]);
|
||||
sizes = Malloc(sizeof(size_t)*MPMY_Nproc());
|
||||
Native_MPMY_Allgather(&nwrite, 1, MPMY_LONG, sizes);
|
||||
MPI_File_get_position(fp->fd, &mpi_offset);
|
||||
Msgf(("Starting offset in MPMY_Fwrite is %lld\n", mpi_offset));
|
||||
for (i = 0; i < MPMY_Procnum(); i++) {
|
||||
mpi_offset += sizes[i];
|
||||
}
|
||||
Msgf(("My offset in MPMY_Fwrite is %lld\n", mpi_offset));
|
||||
Free(sizes);
|
||||
left = nwrite;
|
||||
while (left > 0) {
|
||||
nwrite = (left < MAXIOSIZE) ? left : MAXIOSIZE;
|
||||
Msgf(("write %ld at %lld\n", nwrite, mpi_offset));
|
||||
Msg_flush();
|
||||
MPI_File_write_at(fp->fd, mpi_offset, (void *)p, nwrite, MPI_CHAR, &status);
|
||||
left -= nwrite;
|
||||
p += nwrite;
|
||||
mpi_offset += nwrite;
|
||||
MPI_Get_count(&status, MPI_CHAR, &cnt);
|
||||
if (cnt != nwrite) Error("MPMY_Fwrite has a problem, wrote %d of %ld\n",
|
||||
cnt, nwrite);
|
||||
}
|
||||
}
|
||||
return nitems;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
MPI_Offset mpi_offset;
|
||||
int real_whence = 0;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (whence == MPMY_SEEK_SET) real_whence = MPI_SEEK_SET;
|
||||
if (whence == MPMY_SEEK_CUR) real_whence = MPI_SEEK_CUR;
|
||||
if (whence == MPMY_SEEK_END) real_whence = MPI_SEEK_END;
|
||||
|
||||
mpi_offset = offset; /* potential conversion problem */
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
ret = MPI_File_seek_shared(fp->fd, mpi_offset, real_whence);
|
||||
} else {
|
||||
ret = MPI_File_seek(fp->fd, mpi_offset, real_whence);
|
||||
}
|
||||
if (ret != -1) ret = 0;
|
||||
Msgf(("Fseek to %ld returns %d\n", (long)mpi_offset, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Ftell(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Offset mpi_offset;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_get_position_shared(fp->fd, &mpi_offset);
|
||||
} else {
|
||||
MPI_File_get_position(fp->fd, &mpi_offset);
|
||||
}
|
||||
Msgf(("Ftell returns %ld\n", (long)mpi_offset));
|
||||
return mpi_offset;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Flen(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Offset mpi_offset_current, mpi_offset_end;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_get_position_shared(fp->fd, &mpi_offset_current);
|
||||
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_END);
|
||||
MPI_File_get_position_shared(fp->fd, &mpi_offset_end);
|
||||
MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_SET);
|
||||
} else {
|
||||
MPI_File_get_position(fp->fd, &mpi_offset_current);
|
||||
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_END);
|
||||
MPI_File_get_position(fp->fd, &mpi_offset_end);
|
||||
MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_SET);
|
||||
}
|
||||
Msgf(("Flen returns %ld\n", (long)mpi_offset_end));
|
||||
return mpi_offset_end;
|
||||
}
|
||||
|
||||
size_t
|
||||
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen,
|
||||
size_t nrecs)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
MPI_Offset mpi_offset;
|
||||
MPI_Status status;
|
||||
int cnt;
|
||||
size_t nread = reclen*nrecs;
|
||||
const char *p = buf;
|
||||
|
||||
Msgf(("Fseekrd %ld at %ld\n", (size_t)reclen*nrecs, offset));
|
||||
mpi_offset = offset;
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
MPI_File_read_at_all(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
|
||||
} else {
|
||||
MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status);
|
||||
}
|
||||
MPI_Get_count(&status, MPI_BYTE, &cnt);
|
||||
if (cnt != nread) Error("MPMY_Fseekrd has a problem, got %d expected %ld\n",
|
||||
cnt, nread);
|
||||
return nrecs;
|
||||
}
|
||||
|
||||
#include "io_generic.c"
|
1
external/libsdf/libmpmy/mpmy_mvapich2.c
vendored
Symbolic link
1
external/libsdf/libmpmy/mpmy_mvapich2.c
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
mpmy_mpi.c
|
281
external/libsdf/libmpmy/mpmy_panio.c
vendored
Normal file
281
external/libsdf/libmpmy/mpmy_panio.c
vendored
Normal file
|
@ -0,0 +1,281 @@
|
|||
/* This file contains the parallel I/O suitable for CMMD and NX.
|
||||
It wouldn't be hard to add cubix-syntax as well. Are there any
|
||||
other options? Would they fit in this structure? The only
|
||||
difference between CMMD and NX is in Fopen, where one
|
||||
system calls gopen() and the other calls CMMD_set_io_mode().
|
||||
We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide
|
||||
which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles,
|
||||
while __CM5__ is set by mpmy_cm5.c, which #includes this file.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include "protos.h"
|
||||
#include "mpmy.h"
|
||||
#include "mpmy_io.h"
|
||||
#include "Msgs.h"
|
||||
#include "iozero.h"
|
||||
|
||||
#ifndef EINVAL
|
||||
/* just in case... */
|
||||
#define EINVAL 0
|
||||
#endif
|
||||
|
||||
#define NFILES 4096
|
||||
static struct _File{
|
||||
int fd;
|
||||
int iomode;
|
||||
int iotype;
|
||||
int flags;
|
||||
} _files[NFILES];
|
||||
|
||||
static int do_nfileio;
|
||||
|
||||
MPMYFile *
|
||||
MPMY_Fopen(const char *path, int flags)
|
||||
{
|
||||
int fd;
|
||||
int mode = 0644;
|
||||
int iomode = MPMY_SINGL; /* default */
|
||||
int iotype = 0;
|
||||
int real_flags = 0;
|
||||
|
||||
Msgf(("Fopen %s\n", path));
|
||||
if (flags & MPMY_RDONLY) real_flags |= O_RDONLY;
|
||||
if (flags & MPMY_WRONLY) real_flags |= O_WRONLY;
|
||||
if (flags & MPMY_RDWR) real_flags |= O_RDWR;
|
||||
if (flags & MPMY_APPEND) real_flags |= O_APPEND;
|
||||
if (flags & MPMY_TRUNC) real_flags |= O_TRUNC;
|
||||
if (flags & MPMY_CREAT) real_flags |= O_CREAT;
|
||||
|
||||
/* Should we make sure that only one of them is on?? */
|
||||
if (flags & MPMY_MULTI) iomode = MPMY_MULTI;
|
||||
if (flags & MPMY_SINGL) iomode = MPMY_SINGL;
|
||||
|
||||
if (flags & MPMY_NFILE) iotype = MPMY_NFILE;
|
||||
if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n");
|
||||
if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n");
|
||||
|
||||
if (iotype == MPMY_NFILE) {
|
||||
char real_path[256];
|
||||
sprintf(real_path, "%s.p%03d", path, MPMY_Procnum());
|
||||
Msgf(("Fopen %s in NFILE mode\n", path));
|
||||
fd = open(real_path, real_flags, mode);
|
||||
} else if (flags & MPMY_SINGL) {
|
||||
Msgf(("Fopen %s in SINGL mode\n", path));
|
||||
fd = open(path, real_flags, mode);
|
||||
} else {
|
||||
Msgf(("Fopen %s in MULTI mode\n", path));
|
||||
fd = open(path, real_flags, mode);
|
||||
}
|
||||
|
||||
if (fd >= NFILES) Error("fd too large (%d)\n", fd);
|
||||
if( fd >= 0 ){
|
||||
_files[fd].iomode = iomode;
|
||||
_files[fd].iotype = iotype;
|
||||
Msgf(("Fopen returns %d, iomode=%d, flags=0x%x\n", fd, iomode, flags));
|
||||
return &(_files[fd]);
|
||||
}else{
|
||||
Msgf(("Fopen fails, errno=%d\n", errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Nfileio(int val){
|
||||
int oldval = do_nfileio;
|
||||
do_nfileio = val;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fclose(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) ret = close0(fp->fd);
|
||||
else ret = close(fp->fd);
|
||||
Msgf(("Fclose of %d returns %d\n", fp->fd, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Mkdir(const char *path, int mode){
|
||||
return mkdir0(path, mode);
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fread(void *ptr, int size, int nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) ret = read0(fp->fd, ptr, size*nitems);
|
||||
else ret = read(fp->fd, ptr, size*nitems);
|
||||
|
||||
Msgf(("Fread from %d returns %d\n", fp->fd, ret));
|
||||
if (ret % size) Error("MPMY_Fread has a problem\n");
|
||||
return ret/size;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fwrite(const void *ptr, int size, int nitems, MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) ret= write0(fp->fd, ptr, size*nitems);
|
||||
else ret = write(fp->fd, ptr, size*nitems);
|
||||
/* Msgf(("Fwrite to %d returns %d.\n", fp->fd, ret)); */
|
||||
if (ret % size) Error("MPMY_Fwrite has a problem\n");
|
||||
return ret/size;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
off_t ret;
|
||||
int real_whence = 0;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (whence == MPMY_SEEK_SET) real_whence = SEEK_SET;
|
||||
if (whence == MPMY_SEEK_CUR) real_whence = SEEK_CUR;
|
||||
if (whence == MPMY_SEEK_END) real_whence = SEEK_END;
|
||||
|
||||
if (fp->iotype == MPMY_SINGL) {
|
||||
ret = lseek0(fp->fd, offset, real_whence);
|
||||
} else {
|
||||
ret = lseek(fp->fd, offset, real_whence);
|
||||
}
|
||||
if (ret != -1) ret = 0;
|
||||
Msgf(("Fseek returns %ld\n", (long)ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Ftell(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
off_t ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iotype == MPMY_SINGL) {
|
||||
ret = tell0(fp->fd);
|
||||
} else {
|
||||
ret = lseek(fp->fd, 0L, SEEK_CUR);
|
||||
}
|
||||
Msgf(("Ftell returns %ld\n", (long)ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t
|
||||
MPMY_Flen(MPMYFile *Fp)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
off_t ret;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iotype & MPMY_NFILE) {
|
||||
ret = flen(fp->fd);
|
||||
Msgf(("flen segment %ld\n", (long)ret));
|
||||
if (sizeof(ret) != sizeof(long)) {
|
||||
Error("Bad types in MPMY_Flen\n");
|
||||
}
|
||||
MPMY_Combine(&ret, &ret, 1, MPMY_LONG, MPMY_SUM);
|
||||
} else if (fp->iotype == MPMY_SINGL) {
|
||||
ret = flen0(fp->fd);
|
||||
} else {
|
||||
ret = flen(fp->fd);
|
||||
}
|
||||
Msgf(("Flen returns %ld\n", (long)ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, int reclen,
|
||||
int nrecs)
|
||||
{
|
||||
struct _File *fp = (struct _File *)Fp;
|
||||
int doseek;
|
||||
|
||||
if( fp == NULL ){
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (fp->iomode == MPMY_SINGL) {
|
||||
nrecs = fseekrd0(fp->fd, offset, whence, buf, reclen, nrecs);
|
||||
return nrecs;
|
||||
}
|
||||
|
||||
if( whence == MPMY_SEEK_CUR ){
|
||||
doseek = (offset != 0);
|
||||
}else if( whence == MPMY_SEEK_SET ){
|
||||
/* don't worry about errors. If ftell returns -1, */
|
||||
/* doseek will be turned on, and the fseek below will */
|
||||
/* (probably) fail */
|
||||
doseek = (MPMY_Ftell(Fp) != offset);
|
||||
}else{
|
||||
doseek = 1;
|
||||
}
|
||||
|
||||
if( doseek ){
|
||||
if( MPMY_Fseek(Fp, offset, whence) ){
|
||||
if( whence == MPMY_SEEK_CUR && offset > 0 ){
|
||||
/* Make a final heroic effort to seek by reading forward! */
|
||||
char junk[BUFSIZ];
|
||||
int nleft = offset;
|
||||
while( nleft ){
|
||||
int ntry = ( nleft > sizeof(junk) ) ? sizeof(junk) : nleft;
|
||||
if( MPMY_Fread(junk, ntry, 1, Fp) != 1 ){
|
||||
Error("fseekrd: incremental fread(%#lx, %d, 1, %#lx) failed, errno=%d\n",
|
||||
(unsigned long)junk, ntry,
|
||||
(unsigned long)fp, errno);
|
||||
return -1;
|
||||
}
|
||||
nleft -= ntry;
|
||||
}
|
||||
}else{
|
||||
Error("fseekrd: fseek(%#lx, %lld, %d) failed, errno=%d\n",
|
||||
(unsigned long)fp, offset, whence, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( MPMY_Fread(buf, reclen, nrecs, Fp) != nrecs ){
|
||||
Error("fseekrd: fread(%#lx, %d, %d, %#lx) failed, errno=%d\n",
|
||||
(unsigned long)buf, reclen, nrecs, (unsigned long)fp, errno);
|
||||
return -1;
|
||||
}
|
||||
return nrecs;
|
||||
}
|
||||
|
||||
#include "iozero.c"
|
||||
#include "io_generic.c"
|
262
external/libsdf/libmpmy/mpmy_seq.c
vendored
Normal file
262
external/libsdf/libmpmy/mpmy_seq.c
vendored
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
Not-so-trivial implementation of the mpmy interface for a single process(or)
|
||||
that handles messages sent to itself.
|
||||
|
||||
This is not designed for speed. In fact, it's not designed at all. It's
|
||||
just meant to limp along. I think it's a bad idea to be sending a lot
|
||||
of messages to yourself.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "Msgs.h"
|
||||
#include "mpmy.h"
|
||||
#include "Assert.h"
|
||||
#include "mpmy_io.h"
|
||||
#include "mpmy_time.h"
|
||||
#include "mpmy_abnormal.h"
|
||||
|
||||
#define IN 1
|
||||
#define OUT 2
|
||||
|
||||
#ifdef __SUN4__
|
||||
/* ARCH=sun4 code may have been compiled and linked with __CM5VU__, which
|
||||
means that if we're not careful we'll hit some illegal instructions when
|
||||
we try to call do_grav. This variable sidesteps those Vector-Unit
|
||||
calls at run-time. It's twisted, but it's the price we pay for using
|
||||
ARCH=sun4 for the CM5. */
|
||||
int have_vu = 0;
|
||||
void *VUHeap;
|
||||
int VUaux_allocated;
|
||||
|
||||
#if 0
|
||||
void *aux_alloc_heap(int n){
|
||||
Error("aux_alloc_heap: You shouldn't reach this on a non-cm5 processor!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
struct comm_s{
|
||||
int cnt;
|
||||
int tag;
|
||||
void *buf;
|
||||
int inout;
|
||||
int finished;
|
||||
};
|
||||
|
||||
/* These do a little more than mpmy_alloc_generic. It lets us search */
|
||||
/* the list of allocated requests too. Unfortunately, it takes O(Nreq) */
|
||||
/* time to do a Dealloc or a Match. I'm sure there's something simpler than */
|
||||
/* hashing that would do better, but I'm being dense. */
|
||||
|
||||
#define MAXCOMM 200
|
||||
static struct comm_s _comms[MAXCOMM];
|
||||
static int freecomm[MAXCOMM];
|
||||
static int usedcomm[MAXCOMM];
|
||||
static int mpmy_nfree = 0;
|
||||
static int mpmy_nused = 0;
|
||||
|
||||
static void CommInit(void){
|
||||
int i;
|
||||
for(i=0; i<MAXCOMM; i++){
|
||||
freecomm[i] = i;
|
||||
}
|
||||
mpmy_nfree = MAXCOMM;
|
||||
mpmy_nused = 0;
|
||||
}
|
||||
|
||||
static int CommAlloc(void){
|
||||
int ret;
|
||||
if( mpmy_nfree >= 0 ){
|
||||
ret = freecomm[--mpmy_nfree];
|
||||
usedcomm[mpmy_nused++] = ret;
|
||||
return ret;
|
||||
}else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void CommDealloc(int req){
|
||||
int i;
|
||||
assert(mpmy_nfree < MAXCOMM);
|
||||
for(i=0; i<mpmy_nused; i++){
|
||||
if( usedcomm[i] == req ){
|
||||
usedcomm[i] = usedcomm[--mpmy_nused];
|
||||
break;
|
||||
}
|
||||
}
|
||||
freecomm[mpmy_nfree++] = req;
|
||||
}
|
||||
|
||||
static int find_match(int inout, int tag){
|
||||
int i, ui;
|
||||
struct comm_s *comm;
|
||||
|
||||
for(i=0; i<mpmy_nused; i++){
|
||||
ui = usedcomm[i];
|
||||
comm = &_comms[ui];
|
||||
if( !comm->finished
|
||||
&& (comm->tag == tag || tag == MPMY_TAG_ANY || comm->tag == MPMY_TAG_ANY)
|
||||
&& comm->inout == inout )
|
||||
return ui;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int MPMY_Isend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *reqp){
|
||||
struct comm_s *comm;
|
||||
int req;
|
||||
|
||||
if( dest != 0 )
|
||||
return MPMY_FAILED;
|
||||
req = CommAlloc();
|
||||
if( req < 0 )
|
||||
return MPMY_FAILED;
|
||||
|
||||
comm = &_comms[req];
|
||||
comm->inout = OUT;
|
||||
comm->cnt = cnt;
|
||||
comm->tag = tag;
|
||||
comm->buf = (void *)buf; /* drop const. modifier */
|
||||
comm->finished = 0;
|
||||
*reqp = comm;
|
||||
IncrCounter(&MPMYSendCnt);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *reqp){
|
||||
struct comm_s *comm;
|
||||
int req;
|
||||
|
||||
if( src != 0 && src != MPMY_SOURCE_ANY )
|
||||
return MPMY_FAILED;
|
||||
req = CommAlloc();
|
||||
if( req < 0 )
|
||||
return MPMY_FAILED;
|
||||
|
||||
comm = &_comms[req];
|
||||
comm->inout = IN;
|
||||
comm->cnt = cnt;
|
||||
comm->tag = tag;
|
||||
comm->buf = buf;
|
||||
comm->finished = 0;
|
||||
*reqp = comm;
|
||||
IncrCounter(&MPMYRecvCnt);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_Test(MPMY_Comm_request req, int *flag, MPMY_Status *stat){
|
||||
struct comm_s *comm = req;
|
||||
struct comm_s *mcomm;
|
||||
int match;
|
||||
int ireq = comm - _comms;
|
||||
|
||||
if( comm->finished ){
|
||||
*flag = 1;
|
||||
if( comm->inout == IN && stat ){
|
||||
stat->count = comm->cnt;
|
||||
stat->tag = comm->tag;
|
||||
stat->src = 0;
|
||||
}
|
||||
CommDealloc(ireq);
|
||||
IncrCounter(&MPMYDoneCnt);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
if( comm->inout == IN ){
|
||||
match = find_match(OUT, comm->tag);
|
||||
if( match >= 0 ){
|
||||
mcomm = &_comms[match];
|
||||
if( mcomm->cnt > comm->cnt ){
|
||||
SeriousWarning("MPMY_Test message too long\n");
|
||||
CommDealloc(ireq);
|
||||
return MPMY_FAILED;
|
||||
}
|
||||
memcpy(comm->buf, mcomm->buf, mcomm->cnt);
|
||||
if( stat ){
|
||||
stat->count = mcomm->cnt;
|
||||
stat->tag = mcomm->tag;
|
||||
stat->src = 0;
|
||||
}
|
||||
mcomm->finished = 1;
|
||||
*flag = 1;
|
||||
IncrCounter(&MPMYDoneCnt);
|
||||
CommDealloc(ireq);
|
||||
return MPMY_SUCCESS;
|
||||
}else{
|
||||
*flag = 0;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
}else{
|
||||
match = find_match(IN, comm->tag);
|
||||
if( match >= 0 ){
|
||||
mcomm = &_comms[match];
|
||||
if( comm->cnt > mcomm->cnt ){
|
||||
SeriousWarning("MPMY_Test message too long\n");
|
||||
CommDealloc(ireq);
|
||||
return MPMY_FAILED;
|
||||
}
|
||||
memcpy(mcomm->buf, comm->buf, comm->cnt);
|
||||
mcomm->cnt = comm->cnt;
|
||||
mcomm->tag = comm->tag;
|
||||
mcomm->finished = 1;
|
||||
*flag = 1;
|
||||
IncrCounter(&MPMYDoneCnt);
|
||||
CommDealloc(ireq);
|
||||
return MPMY_SUCCESS;
|
||||
}else{
|
||||
*flag = 0;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype,
|
||||
void *recvbuf, int recvcount, MPMY_Datatype recvtype)
|
||||
{
|
||||
memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[sendtype]);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf)
|
||||
{
|
||||
memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[type]);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf,
|
||||
int *rcounts, int *roffsets)
|
||||
{
|
||||
memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[type]);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MPMY_Init(int *argcp, char ***argvp){
|
||||
CommInit();
|
||||
_MPMY_nproc_ = 1;
|
||||
_MPMY_procnum_ = 0;
|
||||
_MPMY_initialized_ = 1;
|
||||
/* There should really be a better way to opt out of MPMY abnormal
|
||||
signal handling. For now, this will work for programs that might
|
||||
use SDF, but which have their own carefully crafted signal handlers,
|
||||
e.g., SM */
|
||||
if( argcp )
|
||||
_MPMY_setup_absigs();
|
||||
MPMY_OnAbnormal(MPMY_SystemAbort);
|
||||
MPMY_OnAbnormal(MPMY_Abannounce);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef USE_GETTIME
|
||||
#include "timers_gettime.c"
|
||||
#endif
|
||||
|
||||
#ifdef USE_HWCLOCK
|
||||
#include "timers_hwclock.c"
|
||||
#endif
|
||||
|
||||
#include "mpmy_io.c"
|
||||
#include "mpmy_abnormal.c"
|
||||
#include "mpmy_generic.c"
|
85
external/libsdf/libmpmy/timers_gettime.c
vendored
Normal file
85
external/libsdf/libmpmy/timers_gettime.c
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include <time.h>
|
||||
#include "mpmy_time.h"
|
||||
#include "Malloc.h"
|
||||
#include "chn.h"
|
||||
|
||||
static Chn timer_chn;
|
||||
static int initialized;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
struct timespec cpu_start;
|
||||
double cpu_accum;
|
||||
struct timespec wc_start;
|
||||
double wc_accum;
|
||||
} MPMY_Timer;
|
||||
|
||||
void *MPMY_CreateTimer(int type){
|
||||
MPMY_Timer *ret;
|
||||
|
||||
if( initialized == 0 ){
|
||||
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
ret = ChnAlloc(&timer_chn);
|
||||
ret->type = type;
|
||||
MPMY_ClearTimer(ret);
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
int MPMY_DestroyTimer(void *p){
|
||||
ChnFree(&timer_chn, p);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StartTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_CPU_TIME:
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t->cpu_start);
|
||||
break;
|
||||
case MPMY_WC_TIME:
|
||||
clock_gettime(CLOCK_REALTIME, &t->wc_start);
|
||||
break;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StopTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
struct timespec tnow;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_CPU_TIME:
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tnow);
|
||||
t->cpu_accum += (tnow.tv_sec - t->cpu_start.tv_sec) + (tnow.tv_nsec - t->cpu_start.tv_nsec) * 1e-9;
|
||||
break;
|
||||
case MPMY_WC_TIME:
|
||||
clock_gettime(CLOCK_REALTIME, &tnow);
|
||||
t->wc_accum += (tnow.tv_sec - t->wc_start.tv_sec) + (tnow.tv_nsec - t->wc_start.tv_nsec) * 1e-9;
|
||||
break;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_ClearTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
t->cpu_accum = 0.0;
|
||||
t->wc_accum = 0.0;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
double MPMY_ReadTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_CPU_TIME:
|
||||
return t->cpu_accum;
|
||||
case MPMY_WC_TIME:
|
||||
return t->wc_accum;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
106
external/libsdf/libmpmy/timers_hwclock.c
vendored
Normal file
106
external/libsdf/libmpmy/timers_hwclock.c
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include <time.h>
|
||||
#include "mpmy_time.h"
|
||||
#include "Malloc.h"
|
||||
#include "chn.h"
|
||||
|
||||
static Chn timer_chn;
|
||||
static int initialized;
|
||||
|
||||
typedef struct {
|
||||
unsigned long long start;
|
||||
unsigned long long accum;
|
||||
struct timespec wc_start;
|
||||
double wc_accum;
|
||||
int type;
|
||||
} MPMY_Timer;
|
||||
|
||||
#ifdef AMD6100
|
||||
#define DEFAULT_MHZ 2300.0e6
|
||||
#else
|
||||
#define DEFAULT_MHZ 2668.0e6
|
||||
#endif
|
||||
|
||||
static __inline__ unsigned long long rdtsc(void)
|
||||
{
|
||||
unsigned hi, lo;
|
||||
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
|
||||
}
|
||||
|
||||
void *MPMY_CreateTimer(int type){
|
||||
MPMY_Timer *ret;
|
||||
|
||||
if( initialized == 0 ){
|
||||
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
ret = ChnAlloc(&timer_chn);
|
||||
ret->type = type;
|
||||
MPMY_ClearTimer(ret);
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
int MPMY_DestroyTimer(void *p){
|
||||
ChnFree(&timer_chn, p);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_CopyTimer(void *p, void *q)
|
||||
{
|
||||
MPMY_Timer *t = p;
|
||||
MPMY_Timer *u = q;
|
||||
|
||||
*u = *t;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StartTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_CPU_TIME:
|
||||
t->start = rdtsc();
|
||||
break;
|
||||
case MPMY_WC_TIME:
|
||||
clock_gettime(CLOCK_REALTIME, &t->wc_start);
|
||||
break;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StopTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
struct timespec tnow;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_CPU_TIME:
|
||||
t->accum += rdtsc()-t->start;
|
||||
break;
|
||||
case MPMY_WC_TIME:
|
||||
clock_gettime(CLOCK_REALTIME, &tnow);
|
||||
t->wc_accum += (tnow.tv_sec - t->wc_start.tv_sec) + (tnow.tv_nsec - t->wc_start.tv_nsec) * 1e-9;
|
||||
break;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_ClearTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
t->accum = 0;
|
||||
t->wc_accum = 0.0;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
double MPMY_ReadTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_CPU_TIME:
|
||||
return t->accum/DEFAULT_MHZ;
|
||||
case MPMY_WC_TIME:
|
||||
return t->wc_accum;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
59
external/libsdf/libmpmy/timers_mpi.c
vendored
Normal file
59
external/libsdf/libmpmy/timers_mpi.c
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* This file tries to use only MPI-approved timer constructs. */
|
||||
|
||||
/* time.h should define CLOCKS_PER_SECOND and prototype clock() and time()
|
||||
and it should have typedefs for time_t and clock_t. */
|
||||
#include "mpmy_time.h"
|
||||
#include "chn.h"
|
||||
|
||||
static Chn timer_chn;
|
||||
static int initialized;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
double wc_start, wc_accum;
|
||||
} MPMY_Timer;
|
||||
|
||||
void *MPMY_CreateTimer(int type){
|
||||
MPMY_Timer *ret;
|
||||
|
||||
if( initialized == 0 ){
|
||||
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
ret = ChnAlloc(&timer_chn);
|
||||
ret->type = type;
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
int MPMY_DestroyTimer(void *p){
|
||||
ChnFree(&timer_chn, p);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StartTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
t->wc_start = MPI_Wtime();
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StopTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
t->wc_accum += MPI_Wtime() - t->wc_start;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_ClearTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
t->wc_accum = 0.;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
double MPMY_ReadTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
return (double)t->wc_accum;
|
||||
}
|
139
external/libsdf/libmpmy/timers_posix.c
vendored
Normal file
139
external/libsdf/libmpmy/timers_posix.c
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
/* This file tries to use only ANSI/POSIX-approved timer constructs. */
|
||||
/* It should compile correctly everywhere (Ha!) */
|
||||
|
||||
/* time.h should define CLOCKS_PER_SECOND and prototype clock() and time()
|
||||
and it should have typedefs for time_t and clock_t. */
|
||||
#include <time.h>
|
||||
#include "mpmy_time.h"
|
||||
#include "chn.h"
|
||||
#include "Malloc.h"
|
||||
|
||||
#ifndef CLOCKS_PER_SECOND
|
||||
/* We've got a non-standard time.h. At least we have a time.h...*/
|
||||
#ifdef CLOCKS_PER_SEC /* This works for linux */
|
||||
#define CLOCKS_PER_SECOND CLOCKS_PER_SEC
|
||||
#else
|
||||
#define CLOCKS_PER_SECOND 1000000 /* this is just a wild guess!! */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* POSIX only guarantees 'time', which returns a time_t. The option
|
||||
is available for the 'implementor' to make time_t a double. Does
|
||||
the friendly implementor at Sun do this? Nooooo. If we want more
|
||||
precision we have to use gettimeofday, which is a non-POSIX BSD-ism.
|
||||
|
||||
Better still, gettimeofday has mutually incompatible definitions in
|
||||
SVr4 (one argument) and XSH4.2 (two arguments). Sigh...
|
||||
*/
|
||||
#if defined(sun) || defined(__INTEL_SSD__) || defined(_AIX) || defined(__x86_64__)
|
||||
# define USE_GETTIMEOFDAY
|
||||
# include <sys/time.h>
|
||||
#else /* don't use gettimeofday. use time() instead */
|
||||
extern time_t time(time_t *);
|
||||
#endif
|
||||
|
||||
/* This ought to be in one of the system headers... */
|
||||
extern clock_t clock(void);
|
||||
|
||||
static Chn timer_chn;
|
||||
static int initialized;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
clock_t cpu_start, cpu_accum;
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
struct timeval wc_start;
|
||||
struct timeval wc_accum;
|
||||
#else
|
||||
time_t wc_start, wc_accum;
|
||||
#endif
|
||||
} MPMY_Timer;
|
||||
|
||||
void *MPMY_CreateTimer(int type){
|
||||
MPMY_Timer *ret;
|
||||
|
||||
if( initialized == 0 ){
|
||||
ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
ret = ChnAlloc(&timer_chn);
|
||||
ret->type = type;
|
||||
MPMY_ClearTimer(ret);
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
int MPMY_DestroyTimer(void *p){
|
||||
ChnFree(&timer_chn, p);
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StartTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_WC_TIME:
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
gettimeofday(&t->wc_start, 0);
|
||||
#else
|
||||
t->wc_start = time(0);
|
||||
#endif
|
||||
break;
|
||||
case MPMY_CPU_TIME:
|
||||
t->cpu_start = clock();
|
||||
break;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_StopTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_WC_TIME:
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
{
|
||||
struct timeval tnow;
|
||||
gettimeofday(&tnow, 0);
|
||||
t->wc_accum.tv_sec += tnow.tv_sec - t->wc_start.tv_sec;
|
||||
t->wc_accum.tv_usec += tnow.tv_usec - t->wc_start.tv_usec;
|
||||
}
|
||||
#else
|
||||
t->wc_accum += time(0) - t->wc_start;
|
||||
#endif
|
||||
break;
|
||||
case MPMY_CPU_TIME:
|
||||
t->cpu_accum += clock() - t->cpu_start;
|
||||
break;
|
||||
}
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
int MPMY_ClearTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
t->wc_accum.tv_sec = 0;
|
||||
t->wc_accum.tv_usec = 0;
|
||||
#else
|
||||
t->wc_accum = 0;
|
||||
#endif
|
||||
t->cpu_accum = 0;
|
||||
return MPMY_SUCCESS;
|
||||
}
|
||||
|
||||
double MPMY_ReadTimer(void *p){
|
||||
MPMY_Timer *t = p;
|
||||
|
||||
switch(t->type){
|
||||
case MPMY_WC_TIME:
|
||||
#ifdef USE_GETTIMEOFDAY
|
||||
return (double)t->wc_accum.tv_sec + (double)t->wc_accum.tv_usec*1.0e-6;
|
||||
#else
|
||||
return (double)t->wc_accum;
|
||||
#endif
|
||||
case MPMY_CPU_TIME:
|
||||
return (double)t->cpu_accum * (1.0/CLOCKS_PER_SECOND);
|
||||
}
|
||||
return -1.0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue