Skip to content

Commit

Permalink
add python client example
Browse files Browse the repository at this point in the history
  • Loading branch information
wangzhezhe committed Sep 12, 2018
1 parent 364049f commit 364b038
Show file tree
Hide file tree
Showing 14 changed files with 505 additions and 0 deletions.
6 changes: 6 additions & 0 deletions tests/Python/example/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

module load python/3.6.3
module unload openmpi/1.10.1
module load mpich
make
20 changes: 20 additions & 0 deletions tests/Python/example/example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#define MPICH_SKIP_MPICXX 1
#define OMPI_SKIP_MPICXX 1

#include <mpi.h>
#include <stdio.h>

void sayhello(MPI_Comm comm) {
int size, rank;
char pname[MPI_MAX_PROCESSOR_NAME]; int len;
if (comm == MPI_COMM_NULL) {
printf("You passed MPI_COMM_NULL !!!\n");
return;
}
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
MPI_Get_processor_name(pname, &len);
pname[len] = 0;
printf("Hello, World! I am process %d of %d on %s.\n",
rank, size, pname);
}
18 changes: 18 additions & 0 deletions tests/Python/example/example.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
%module example

%{
#include <mpi.h>
#include "example.c"
%}

%include mpi4py/mpi4py.i

%mpi4py_typemap(Comm, MPI_Comm);

void sayhello(MPI_Comm comm);

/*
* Local Variables:
* mode: C
* End:
*/
36 changes: 36 additions & 0 deletions tests/Python/example/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.PHONY: default
default: build example clean

PYTHON = python
PYTHON_CONFIG = ${PYTHON} ../python-config
MPI4PY_INCLUDE = ${shell ${PYTHON} -c 'import mpi4py; print( mpi4py.get_include() )'}


SWIG = swig
SWIG_PY = ${SWIG} -python
.PHONY: src
src: example_wrap.c
example_wrap.c: example.i
${SWIG_PY} -I${MPI4PY_INCLUDE} -o $@ $<

MPICC = mpicc
CFLAGS = -fPIC ${shell ${PYTHON_CONFIG} --includes}
LDFLAGS = -shared ${shell ${PYTHON_CONFIG} --libs}
SO = ${shell ${PYTHON_CONFIG} --extension-suffix}
.PHONY: build
build: _example${SO}
_example${SO}: example_wrap.c
${MPICC} ${CFLAGS} -I${MPI4PY_INCLUDE} -o $@ $< ${LDFLAGS}


MPIEXEC = mpiexec
NP_FLAG = -n
NP = 5
.PHONY: example
example: build
${MPIEXEC} ${NP_FLAG} ${NP} ${PYTHON} testexample.py


.PHONY: clean
clean:
${RM} example_wrap.c example.py* _example${SO}
8 changes: 8 additions & 0 deletions tests/Python/example/testexample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from mpi4py import MPI
import example as ex

null = MPI.COMM_NULL
ex.sayhello(null)

comm = MPI.COMM_WORLD
ex.sayhello(comm)
93 changes: 93 additions & 0 deletions tests/Python/getdata.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* put.c : Example 1: DataSpaces put tutorial
* This example will show you the simplest way
* to put a 1D array of 3 elements into the DataSpace.
* */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "dataspaces.h"
#include "mpi.h"

int get_data_test(double *data, int n)
{
int i = 0;
for (i = 0; i < n; i++)
{
data[i] = i * 0.1;
}
return 0;
}

int get_data(MPI_Comm pgcomm, int pndim, double *data, int n)
{

int err;
int nprocs, rank;

MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm gcomm = MPI_COMM_WORLD;
MPI_Barrier(gcomm);

printf("in c file nprocs %d rank %d\n", nprocs, rank);
printf("curr ndim is %d\n", pndim);

// Initalize DataSpaces
// # of Peers, Application ID, ptr MPI comm, additional parameters
// # Peers: Number of connecting clients to the DS server
// Application ID: Unique idenitifier (integer) for application
// Pointer to the MPI Communicator, allows DS Layer to use MPI barrier func
// Addt'l parameters: Placeholder for future arguments, currently NULL.
// the first parameter should be same with the number of threads to access server (namely -n after mpiexec)
// we use -n 2 (defined at run.sh)for this example
// the second parameter is used to label current application, one application/program should have unique appid
// use 1 for putdata and 2 for get data
dspaces_init(2, 2, &gcomm, NULL);

sleep(1);

int timestep = 0;

// DataSpaces: Lock Mechanism
// Usage: Prevent other process from modifying
// data at the same time as ours
//dspaces_lock_on_write("my_test_lock", &gcomm);

//Name the Data that will be writen
char var_name[128];
sprintf(var_name, "ex1_sample_data");

// Create integer array, size 3
// We will store the data we get out of the DataSpace
// in this array.
// instead of using malloc to get new data, using data array sent from python
//double *getdata = malloc(3 * sizeof(int));

// Define the dimensionality of the data to be received
int ndim = 1;

// Prepare LOWER and UPPER bound dimensions
uint64_t lb[1] = {0}, ub[1] = {0};

// DataSpaces: Get data array from the space
// Usage: dspaces_get(Name of variable, version num,
// size (in bytes of each element), dimensions for bounding box,
// lower bound coordinates, upper bound coordinates,
// ptr to data buffer
dspaces_get(var_name, timestep, 3 * sizeof(double), ndim,
lb, ub, data);

printf("Timestep %d: get data %lf %lf %lf\n",
timestep, data[0], data[1], data[2]);

// DataSpaces: Release our lock on the data
dspaces_unlock_on_read("my_test_lock", &gcomm);

// DataSpaces: Finalize and clean up DS process
common_finalize();

MPI_Barrier(gcomm);
MPI_Finalize;

return 0;
}
30 changes: 30 additions & 0 deletions tests/Python/getdata.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
%module getdata

%{
#define SWIG_FILE_WITH_INIT
#include "mpi.h"
#include "getdata.c"
%}

%include mpi4py/mpi4py.i
%include "numpy.i"

%init %{
import_array();
%}

%mpi4py_typemap(Comm, MPI_Comm);

%apply (double* INPLACE_ARRAY1, int DIM1) {(double* data, int n)};

int get_data_test(double *data, int n);
int get_data(MPI_Comm gcomm, int pndim, double *data, int n);


/*
* Local Variables:
* mode: C
* End:
* refer to http://numpy-discussion.10968.n7.nabble.com/Numpy-SWIG-with-arrays-in-input-and-output-of-a-function-td29411.html
* refer to https://docs.scipy.org/doc/numpy/reference/swig.interface-file.html?highlight=array
*/
52 changes: 52 additions & 0 deletions tests/Python/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.PHONY: default
default: buildput buildget runtest

PYTHON = python
PYTHON_CONFIG = ${PYTHON} ./python-config
MPI4PY_INCLUDE = ${shell ${PYTHON} -c 'import mpi4py; print( mpi4py.get_include() )'}
NUMPY_INCLUDE = ${shell ${PYTHON} -c 'import numpy; print( numpy.get_include() )'}
PREFIX = /home1/zw241/dataspaces
INCLUDES = -I$(PREFIX)/include
DSCOMMON = ../C/common.o
LFLAG = -L/home1/zw241/dataspaces/install/lib -ldspaces -ldart -ldscommon -ldspacesf -lpthread -lm -lrt -libverbs -lrdmacm
CFLAGS = -Wall -g

SWIG = swig
SWIG_PY = ${SWIG} -python
.PHONY: src
src: putdata_wrap.c
putdata_wrap.c: putdata.i
[ -f ./numpy.i ] && echo "numpy.i already here, good" || wget https://raw.githubusercontent.com/numpy/numpy/master/tools/swig/numpy.i
${SWIG_PY} -I${MPI4PY_INCLUDE} -I${NUMPY_INCLUDE} $(INCLUDES) -o $@ $<

src: getdata_wrap.c
getdata_wrap.c: getdata.i
[ -f ./numpy.i ] && echo "numpy.i already here, good" || wget https://raw.githubusercontent.com/numpy/numpy/master/tools/swig/numpy.i
${SWIG_PY} -I${MPI4PY_INCLUDE} -I${NUMPY_INCLUDE} $(INCLUDES) -o $@ $<


MPICC = mpicc
CFLAGS = -fPIC ${shell ${PYTHON_CONFIG} --includes}
LDFLAGS = -shared ${shell ${PYTHON_CONFIG} --libs}
SO = ${shell ${PYTHON_CONFIG} --extension-suffix}

.PHONY: buildput
buildput: _putdata${SO}
_putdata${SO}: putdata_wrap.c
${MPICC} ${CFLAGS} -I${MPI4PY_INCLUDE} -I${NUMPY_INCLUDE} $(INCLUDES) $(DSCOMMON) $(LFLAG) -o $@ $< ${LDFLAGS}

.PHONY: buildget
buildget: _getdata${SO}
_getdata${SO}: getdata_wrap.c
${MPICC} ${CFLAGS} -I${MPI4PY_INCLUDE} -I${NUMPY_INCLUDE} $(INCLUDES) $(DSCOMMON) $(LFLAG) -o $@ $< ${LDFLAGS}


.PHONY: runtest
runtest: buildget buildput
/bin/bash ./run.sh


.PHONY: clean
clean:
${RM} putdata_wrap.c putdata.py* _putdata${SO} *.o
${RM} getdata_wrap.c getdata.py* _getdata${SO} *.o
83 changes: 83 additions & 0 deletions tests/Python/putdata.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* put.c : Example 1: DataSpaces put tutorial
* This example will show you the simplest way
* to put a 1D array of 3 elements into the DataSpace.
* */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "dataspaces.h"
#include "mpi.h"

int put_data(MPI_Comm pgcomm, int pndim , double *data, int n)
{
printf("array len %d\n", n);
int i = 0;
for (i = 0; i < n; i++)
{
printf("index %d value %lf\n", data[i]);
}
int err;
int nprocs, rank;

MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm gcomm = MPI_COMM_WORLD;
MPI_Barrier(gcomm);

printf("in c file nprocs %d rank %d\n", nprocs, rank);
printf("curr ndim is %d\n", pndim);

// Initalize DataSpaces
// # of Peers, Application ID, ptr MPI comm, additional parameters
// # Peers: Number of connecting clients to the DS server
// Application ID: Unique idenitifier (integer) for application
// Pointer to the MPI Communicator, allows DS Layer to use MPI barrier func
// Addt'l parameters: Placeholder for future arguments, currently NULL.
// the first parameter should be same with the number of threads to access server (namely -n after mpiexec)
// the second parameter is used to label current application, one application/program should have unique appid
// init is only needed to call once for multiple timesteps
dspaces_init(2, 1, &gcomm, NULL);

int timestep=0;

sleep(1);

// DataSpaces: Lock Mechanism
// Usage: Prevent other process from modifying
// data at the same time as ours
//dspaces_lock_on_write("my_test_lock", &gcomm);

//Name the Data that will be writen
char var_name[128];
sprintf(var_name, "ex1_sample_data");

printf("Timestep %d: put data %lf %lf %lf\n",
timestep, data[0], data[1], data[2]);

// ndim: Dimensions for application data domain
// In this case, our data array is 1 dimensional
int ndim = pndim;

// Prepare LOWER and UPPER bound dimensions
// In this example, we will put all data into a
// one dimention array lb=(0) up=(2)
uint64_t lb[1] = {0}, ub[1] = {2};

// DataSpaces: Put data array into the space
// Usage: dspaces_put(Name of variable, version num,
// size (in bytes of each element), dimensions for bounding box,
// lower bound coordinates, upper bound coordinates,
// ptr to data buffer
dspaces_put(var_name, timestep, 3 * sizeof(double), ndim, lb, ub, data);

// DataSpaces: Release our lock on the data
dspaces_unlock_on_write("my_test_lock", &gcomm);

// DataSpaces: Finalize and clean up DS process
common_finalize();

MPI_Barrier(gcomm);
MPI_Finalize;

return 0;
}
32 changes: 32 additions & 0 deletions tests/Python/putdata.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%module putdata

%{
#define SWIG_FILE_WITH_INIT
#include "mpi.h"
#include "putdata.c"
%}

%include mpi4py/mpi4py.i
%include "numpy.i"

%init %{
import_array();
%}

%mpi4py_typemap(Comm, MPI_Comm);

/*
refer to https://docs.scipy.org/doc/numpy/reference/swig.interface-file.html
for 2d and 3d array
*/
%apply (double* IN_ARRAY1, int DIM1) {(double* data, int n)};


int put_data(MPI_Comm gcomm, int pndim, double *data, int n);


/*
* Local Variables:
* mode: C
* End:
*/
Loading

0 comments on commit 364b038

Please sign in to comment.