Skip to content

Commit a043387

Browse files
ritvikraostevenqie
andauthored
CCS in Charm4Py (#289)
* initial changes * fix string allocation in cython (still need to fix registration) * start python interfacing * register recvRemoteMessage: * ccs server example * build finished * add to gitignore * example compiling * fix registration of handler * better reduction * readme for the example * ccs communication working * remove vscode json * readme changes, everything is working * Delete .vscode/settings.json * fix bug in example with uncaught null at the end of msg * remove comment * variable renaming --------- Co-authored-by: Steven Qie <[email protected]> Co-authored-by: Steven Qie <[email protected]>
1 parent b2dabf8 commit a043387

File tree

8 files changed

+143
-0
lines changed

8 files changed

+143
-0
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ charm4py/_version.py
66
charm4py/charmlib/*.o
77
charm4py/charmlib/*.so
88
charm4py/charmlib/charmlib_cython.c
9+
charm4py/charmlib/charmlib_cython.cpp
10+
charm4py/charmlib/charmlib_cython.html
911
charm4py/charmlib/_charmlib_cffi.c
1012
charm4py/charmlib/build/
13+
charm4py.egg-info/
14+
charm4py/c_object_store.cpp
15+
charm4py/c_object_store.html
1116
__pycache__
1217

1318
# ignore some common tmp files

charm4py/charm.py

+21
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ def __init__(self):
153153
# TODO: maybe implement this buffer in c++
154154
self.future_get_buffer = {}
155155

156+
#registered methods for ccs
157+
self.ccs_methods = {}
158+
156159
def __init_profiling__(self):
157160
# these are attributes used only in profiling mode
158161
# list of Chare types that are registered and used internally by the runtime
@@ -1092,6 +1095,24 @@ def LBTurnInstrumentOn(self):
10921095
def LBTurnInstrumentOff(self):
10931096
self.lib.LBTurnInstrumentOff()
10941097

1098+
#functions for ccs
1099+
def CcsRegisterHandler(self, handlername, handler):
1100+
self.ccs_methods[handlername] = handler
1101+
self.lib.CcsRegisterHandler(handlername, handler)
1102+
1103+
def CcsIsRemoteRequest(self):
1104+
self.lib.isRemoteRequest()
1105+
1106+
def CcsSendReply(self, message):
1107+
self.lib.CcsSendReply(message)
1108+
1109+
def callHandler(self, handlername, data):
1110+
if handlername in self.ccs_methods:
1111+
self.ccs_methods[handlername](data)
1112+
else:
1113+
raise Charm4PyError('Handler ' + handlername + ' not registered')
1114+
1115+
10951116

10961117
class CharmRemote(Chare):
10971118

charm4py/charmlib/ccharm.pxd

+33
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,39 @@ cdef extern from "charm.h":
7070
void CkStartQDExt_SectionCallback(int sid_pe, int sid_cnt, int rootPE, int ep);
7171
void CcdCallFnAfter(void (*CcdVoidFn)(void *userParam,double curWallTime), void *arg, double msecs);
7272

73+
cdef extern from "conv-header.h":
74+
ctypedef void (*CmiHandler)(void* )
75+
cdef const int CmiReservedHeaderSize
76+
77+
cdef extern from "sockRoutines.h":
78+
79+
ctypedef struct skt_ip_t:
80+
int tag
81+
82+
ctypedef struct ChMessageInt_t:
83+
unsigned char[4] data
84+
85+
cdef extern from "ccs-server.h":
86+
87+
ctypedef struct CcsSecAttr:
88+
skt_ip_t ip
89+
ChMessageInt_t port
90+
ChMessageInt_t replySalt
91+
unsigned char auth
92+
unsigned char level
93+
94+
ctypedef struct CcsImplHeader:
95+
CcsSecAttr attr
96+
char[32] handler
97+
ChMessageInt_t pe
98+
ChMessageInt_t replyFd
99+
ChMessageInt_t len
100+
101+
cdef extern from "conv-ccs.h":
102+
void CcsRegisterHandlerExt(const char *ccs_handlername, void *fn);
103+
int CcsIsRemoteRequest();
104+
void CcsSendReply(int replyLen, const void *replyData);
105+
73106

74107
cdef extern from "spanningTree.h":
75108
void getPETopoTreeEdges(int pe, int rootPE, int *pes, int numpes, unsigned int bfactor,

charm4py/charmlib/charmlib_cython.pyx

+41
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_ANY_CON
99
from cpython.tuple cimport PyTuple_New, PyTuple_SET_ITEM
1010
from cpython.int cimport PyInt_FromSsize_t
1111
from cpython.ref cimport Py_INCREF
12+
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
13+
from cython.operator cimport dereference
1214

1315
from ..charm import Charm4PyError
1416
from .. import reduction as red
@@ -36,6 +38,8 @@ cdef object np_number = np.number
3638

3739
# ------ global constants ------
3840

41+
cdef dict _ccs_handlers = {}
42+
3943
cdef enum:
4044
NUM_DCOPY_BUFS = 60 # max number of dcopy buffers
4145

@@ -312,6 +316,28 @@ cdef object times = [0.0] * 3 # track time in [charm reduction callbacks, custom
312316
cdef bytes localMsg = b'L:' + (b' ' * sizeof(int))
313317
cdef char* localMsg_ptr = <char*>localMsg
314318

319+
#cdef const int CmiReservedHeaderSize s= getCmiReservedHeaderSize()
320+
321+
cdef struct remoteMsg:
322+
int header_length
323+
int data_length
324+
char handler_name[32] # we know it can't be longer
325+
char data[1024] #assume generous length at end
326+
327+
cdef void recvRemoteMessage(void *msg) noexcept:
328+
329+
cdef void *shiftedMsg = msg + CmiReservedHeaderSize #move past reserved header
330+
cdef remoteMsg* incomingMsgPtr = <remoteMsg*> shiftedMsg
331+
cdef int handler_length = incomingMsgPtr.header_length
332+
cdef int data_length = incomingMsgPtr.data_length
333+
334+
# turn char arrays into strings
335+
336+
handler_name = incomingMsgPtr.handler_name[:handler_length].decode('utf-8')
337+
data = incomingMsgPtr.data[:data_length].decode('utf-8')
338+
339+
charm.callHandler(handler_name, data)
340+
315341

316342
class CharmLib(object):
317343

@@ -826,6 +852,21 @@ class CharmLib(object):
826852
def scheduleTagAfter(self, int tag, double msecs):
827853
CcdCallFnAfter(CcdCallFnAfterCallback, <void*>tag, msecs)
828854

855+
def CcsRegisterHandler(self, str handlername, object handler):
856+
cdef bytes handler_bytes = handlername.encode("utf-8")
857+
cdef const char* c_handlername = handler_bytes
858+
CcsRegisterHandlerExt(c_handlername, <void *>recvRemoteMessage)
859+
860+
def isRemoteRequest(self):
861+
return bool(CcsIsRemoteRequest())
862+
863+
def CcsSendReply(self, str message):
864+
cdef bytes message_bytes = message.encode("utf-8")
865+
cdef const char* replyData = message_bytes
866+
867+
cdef int replyLen = len(message_bytes)
868+
CcsSendReply(replyLen, <const void*>replyData)
869+
829870

830871
# first callback from Charm++ shared library
831872
cdef void registerMainModule() noexcept:

docs/install.rst

+6
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ the charm directory and run the following build command, then build Charm4Py::
5858
$ cd ../..
5959
$ pip install .
6060

61+
On MacOS, you may need to set your DYLD_LIBRARY_PATH so that the dynamic linker can find Charm++ libraries. For example:
62+
63+
$ export DYLD_LIBRARY_PATH=<charm_install_folder>/lib
64+
65+
Replace <charm_install_folder> with the path where you built/installed Charm++(usually this is the charm_src/charm folder)
66+
6167
Finally, if necessary, when installing dependencies or when running the install script, add the --user
6268
option to the Python command to complete the installation without permission errors.
6369

examples/ccs/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
### Instructions to run CCS Example
2+
3+
1. Start up your python virtual env if using one
4+
2. Boot up the server through the command: python -m charmrun.start +p<N> ++server ++local ccs_server.py
5+
3. Grab and store the the Server IP and Server Port that will appear in stdout when you run the above command
6+
4. In another terminal, cd to the converse/ccstest example in the charm++ repository and run a client program through the command: ./client server_ip server_port

examples/ccs/ccs_server.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from charm4py import charm, Chare, Array, Future, Reducer, Group
2+
3+
def handler(msg):
4+
print("CCS Ping handler called on " + str(charm.myPe()))
5+
6+
msg = msg.rstrip('\x00') #removes null characters from the end
7+
answer = "Hello to sender " + str(msg) + " from PE " + str(charm.myPe()) + ".\n"
8+
# send the answer back to the client
9+
charm.CcsSendReply(answer)
10+
11+
class RegisterPerChare(Chare):
12+
13+
def register(self, return_future, handler):
14+
charm.CcsRegisterHandler("ping2", handler)
15+
charm.CcsRegisterHandler("ping", handler)
16+
self.reduce(return_future, Reducer.nop)
17+
18+
def main(args):
19+
# No need to initialize converse, because charm.start does this
20+
# just register the handler
21+
reg_wait = Future()
22+
registers = Group(RegisterPerChare)
23+
registers.register(reg_wait, handler)
24+
reg_wait.get()
25+
print("CCS Handlers registered . Waiting for net requests...")
26+
27+
28+
charm.start(main)

setup.py

+3
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,11 @@ class _renameInstalled(_install_lib):
263263
def __init__(self, *args, **kwargs):
264264
_install_lib.__init__(self, *args, **kwargs)
265265

266+
266267
def install(self):
267268
log.info("Renaming libraries")
268269
outfiles = _install_lib.install(self)
270+
'''
269271
for file in outfiles:
270272
if "c_object_store" in file and system == "darwin":
271273
direc = os.path.dirname(file)
@@ -285,6 +287,7 @@ def install(self):
285287
install_name_command += "/charmlib_cython.*.so"
286288
log.info(install_name_command)
287289
os.system(install_name_command)
290+
'''
288291
return outfiles
289292

290293

0 commit comments

Comments
 (0)