Newer
Older
* Distributed under the OSI-approved Apache License, Version 2.0. See
* accompanying file Copyright.txt for details.
*
* ADIOS is freely available under the terms of the BSD license described
* in the COPYING file in the top level directory of this source distribution.
*
* Copyright (c) 2008 - 2009. UT-BATTELLE, LLC. All rights reserved.
*/
/*
A dummy MPI implementation for the BP READ API, to have an MPI-free version
of the API
*/
#define __STDC_FORMAT_MACROS
#include <cinttypes>
#include <cstdint>
#include <cstring>
#if defined(__APPLE__) || defined(__WIN32__) || defined(__CYGWIN__)
#define lseek64 lseek
#define open64 open
#endif
*/
#include <cinttypes>
#include <cstdio>
#include <cstring>
#include <chrono>
#include <string>
// remove warnings on Windows
#ifdef _WIN32
#pragma warning(disable : 4996) // fopen
#pragma warning(disable : 4477) // strcpy, sprintf
namespace mpi
{
static char mpierrmsg[MPI_MAX_ERROR_STRING];
int MPI_Init(int * /*argc*/, char *** /*argv*/)
mpierrmsg[0] = '\0';
return MPI_SUCCESS;
mpierrmsg[0] = '\0';
return MPI_SUCCESS;
*flag = 1;
return MPI_SUCCESS;
int MPI_Comm_split(MPI_Comm /*comm*/, int /*color*/, int /*key*/,
MPI_Comm * /*comm_out*/)
int MPI_Barrier(MPI_Comm /*comm*/) { return MPI_SUCCESS; }
int MPI_Bcast(void * /*buffer*/, int /*count*/, MPI_Datatype /*datatype*/,
int /*root*/, MPI_Comm /*comm*/)
}
int MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm)
{
*newcomm = comm;
return MPI_SUCCESS;
int MPI_Comm_rank(MPI_Comm /*comm*/, int *rank)
*rank = 0;
return MPI_SUCCESS;
int MPI_Comm_size(MPI_Comm /*comm*/, int *size)
*size = 1;
return MPI_SUCCESS;
*comm = 0;
return MPI_SUCCESS;
MPI_Comm MPI_Comm_f2c(MPI_Fint comm) { return comm; }
int MPI_Gather(const void *sendbuf, int sendcnt, MPI_Datatype sendtype,
void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root,
MPI_Comm comm)
int ier = MPI_SUCCESS;
size_t n = 0, nsent = 0, nrecv = 0;
}
if (comm == MPI_COMM_NULL || root)
{
ier = MPI_ERR_COMM;
}
switch (sendtype)
{
case MPI_CHAR:
n = sizeof(char);
break;
case MPI_UNSIGNED:
n = sizeof(unsigned int);
break;
case MPI_UNSIGNED_LONG:
n = sizeof(unsigned long);
break;
case MPI_UNSIGNED_LONG_LONG:
n = sizeof(unsigned long long);
break;
return MPI_ERR_TYPE;
}
nsent = n * sendcnt;
case MPI_CHAR:
nrecv = sizeof(char);
break;
nrecv = sizeof(int);
break;
case MPI_UNSIGNED:
nrecv = sizeof(unsigned int);
break;
case MPI_UNSIGNED_LONG:
nrecv = sizeof(unsigned long);
break;
case MPI_UNSIGNED_LONG_LONG:
nrecv = sizeof(unsigned long long);
break;
return MPI_ERR_TYPE;
}
nrecv = n * recvcnt;
if (nrecv != nsent)
{
ier = MPI_ERR_COUNT;
}
if (ier == MPI_SUCCESS)
{
std::memcpy(recvbuf, sendbuf, nsent);
std::snprintf(mpierrmsg, ier, "could not gather data\n");
int MPI_Gatherv(const void *sendbuf, int sendcnt, MPI_Datatype sendtype,
void *recvbuf, const int *recvcnts, const int * /*displs */,
MPI_Datatype recvtype, int root, MPI_Comm comm)
{
ier = MPI_Gather(sendbuf, sendcnt, sendtype, recvbuf, *recvcnts, recvtype,
root, comm);
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int recvcount, MPI_Datatype recvtype,
MPI_Comm comm)
{
return MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount,
recvtype, 0, comm);
int MPI_Scatter(const void *sendbuf, int sendcnt, MPI_Datatype sendtype,
void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root,
MPI_Comm comm)
{
int ier = MPI_SUCCESS;
size_t n = 0, nsent = 0, nrecv = 0;
if (!sendbuf || !recvbuf)
{
ier = MPI_ERR_BUFFER;
}
if (comm == MPI_COMM_NULL || root)
{
ier = MPI_ERR_COMM;
}
switch (sendtype)
{
return MPI_ERR_TYPE;
}
nsent = n * sendcnt;
nrecv = sizeof(int);
break;
return MPI_ERR_TYPE;
}
nrecv = n * recvcnt;
if (nrecv != nsent)
{
ier = MPI_ERR_COUNT;
}
if (ier == MPI_SUCCESS)
{
std::memcpy(recvbuf, sendbuf, nsent);
std::snprintf(mpierrmsg, ier, "could not scatter data\n");
int MPI_Scatterv(const void *sendbuf, const int *sendcnts, const int *displs,
MPI_Datatype sendtype, void *recvbuf, int recvcnt,
MPI_Datatype recvtype, int root, MPI_Comm comm)
{
int ier = MPI_SUCCESS;
if (!sendcnts || !displs)
{
ier = MPI_ERR_BUFFER;
}
if (ier == MPI_SUCCESS)
{
ier = MPI_Scatter(sendbuf, *sendcnts, sendtype, recvbuf, recvcnt,
recvtype, root, comm);
}
return ier;
int MPI_Recv(void * /*recvbuffer*/, int /*count*/, MPI_Datatype /*type*/,
int /*source*/, int /*tag*/, MPI_Comm /*comm*/,
MPI_Status * /*status*/)
int MPI_Irecv(void * /*recvbuffer*/, int /*count*/, MPI_Datatype /*type*/,
int /*source*/, int /*tag*/, MPI_Comm /*comm*/,
MPI_Request * /*request*/)
int MPI_Send(const void * /*sendbuffer*/, int /*count*/, MPI_Datatype /*type*/,
int /*destination*/, int /*tag*/, MPI_Comm /*comm*/)
int MPI_Isend(const void * /*recvbuffer*/, int /*count*/, MPI_Datatype /*type*/,
int /*source*/, int /*tag*/, MPI_Comm /*comm*/,
MPI_Request * /*request*/)
int MPI_Wait(MPI_Request * /*request*/, MPI_Status * /*status*/) { return 0; }
int MPI_File_open(MPI_Comm /*comm*/, const char *filename, int amode,
MPI_Info /*info*/, MPI_File *fh)
std::string mode;
if (amode | MPI_MODE_RDONLY)
mode += "r";
}
if (amode | MPI_MODE_WRONLY)
{
mode += "w";
}
if (amode | MPI_MODE_APPEND)
{
mode += "a";
}
mode += "b";
if (!*fh)
{
std::snprintf(mpierrmsg, MPI_MAX_ERROR_STRING, "File not found: %s",
filename);
return -1;
}
return MPI_SUCCESS;
int MPI_File_close(MPI_File *fh) { return fclose(*fh); }
int MPI_File_get_size(MPI_File fh, MPI_Offset *size)
{
fseek(fh, 0, SEEK_END); // go to end, returned is the size in bytes
long endpos = std::ftell(fh);
std::fseek(fh, curpos, SEEK_SET); // go back where we were
*size = static_cast<MPI_Offset>(endpos);
// printf("MPI_File_get_size: fh=%d, size=%lld\n", fh, *size);
return MPI_SUCCESS;
}
int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype,
MPI_Status *status)
{
// FIXME: int count can read only 2GB (*datatype size) array at max
size_t bytes_to_read = static_cast<size_t>(count) * datatype;
size_t bytes_read;
bytes_read = std::fread(buf, 1, bytes_to_read, fh);
if (bytes_read != bytes_to_read)
{
std::snprintf(mpierrmsg, MPI_MAX_ERROR_STRING,
"\n",
(unsigned long long)bytes_to_read,
(unsigned long long)bytes_read);
return -2;
}
*status = bytes_read;
// printf("MPI_File_read: fh=%d, count=%d, typesize=%d, bytes read=%lld\n",
// fh, count, datatype, *status);
return MPI_SUCCESS;
}
int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence)
{
return std::fseek(fh, offset, whence) == MPI_SUCCESS;
int MPI_Get_count(const MPI_Status *status, MPI_Datatype, int *count)
*count = static_cast<int>(*status);
return MPI_SUCCESS;
int MPI_Error_string(int /*errorcode*/, char *string, int *resultlen)
// std::sprintf(string, "Dummy lib does not know error strings.
std::strcpy(string, mpierrmsg);
*resultlen = static_cast<int>(std::strlen(string));
std::chrono::duration<double> now =
std::chrono::high_resolution_clock::now().time_since_epoch();
return now.count();
}
int MPI_Get_processor_name(char *name, int *resultlen)
{
std::sprintf(name, "0");
*resultlen = 1;
return 0;
int MPI_Reduce(const void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
{
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
switch (datatype)
{
case MPI_CHAR:
if (op == MPI_SUM)
{
char *recvBuffer = reinterpret_cast<char *>(recvbuf);
const char *sendBuffer = reinterpret_cast<const char *>(sendbuf);
*recvBuffer = std::accumulate(sendBuffer, sendBuffer + count, 0);
}
break;
case MPI_INT:
if (op == MPI_SUM)
{
int *recvBuffer = reinterpret_cast<int *>(recvbuf);
const int *sendBuffer = reinterpret_cast<const int *>(sendbuf);
*recvBuffer = std::accumulate(sendBuffer, sendBuffer + count, 0);
}
break;
case MPI_UNSIGNED:
if (op == MPI_SUM)
{
unsigned int *recvBuffer =
reinterpret_cast<unsigned int *>(recvbuf);
const unsigned int *sendBuffer =
reinterpret_cast<const unsigned int *>(sendbuf);
*recvBuffer = std::accumulate(sendBuffer, sendBuffer + count, 0);
}
break;
case MPI_UNSIGNED_LONG:
if (op == MPI_SUM)
{
unsigned long int *recvBuffer =
reinterpret_cast<unsigned long int *>(recvbuf);
const unsigned long int *sendBuffer =
reinterpret_cast<const unsigned long int *>(sendbuf);
*recvBuffer = std::accumulate(sendBuffer, sendBuffer + count, 0);
}
break;
case MPI_UNSIGNED_LONG_LONG:
if (op == MPI_SUM)
{
unsigned long long int *recvBuffer =
reinterpret_cast<unsigned long long int *>(recvbuf);
const unsigned long long int *sendBuffer =
reinterpret_cast<const unsigned long long int *>(sendbuf);
*recvBuffer = std::accumulate(sendBuffer, sendBuffer + count, 0);
}
break;
default:
return MPI_ERR_TYPE;
}
return 0;
}
} // end namespace mpi