From 60894e585d7f494d9ad32afd452a57f8849ceff6 Mon Sep 17 00:00:00 2001 From: mquinson Date: Sun, 2 Oct 2005 19:28:02 +0000 Subject: [PATCH 1/1] Add a yummy matrix multiplication rpc thing git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@1743 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- ChangeLog | 4 +- configure.ac | 2 + doc/module-gras.doc | 148 +++++++++++++++- examples/gras/Makefile.am | 2 +- examples/gras/mmrpc/.cvsignore | 8 + examples/gras/mmrpc/Makefile.am | 23 +++ examples/gras/mmrpc/mmrpc.c | 213 +++++++++++++++++++++++ examples/gras/mmrpc/mmrpc_deployment.xml | 11 ++ examples/gras/mmrpc/test_rl.in | 11 ++ examples/gras/mmrpc/test_sg.in | 9 + 10 files changed, 425 insertions(+), 6 deletions(-) create mode 100644 examples/gras/mmrpc/.cvsignore create mode 100644 examples/gras/mmrpc/Makefile.am create mode 100644 examples/gras/mmrpc/mmrpc.c create mode 100644 examples/gras/mmrpc/mmrpc_deployment.xml create mode 100755 examples/gras/mmrpc/test_rl.in create mode 100755 examples/gras/mmrpc/test_sg.in diff --git a/ChangeLog b/ChangeLog index 35c5ffacfd..d89fbfdaa5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,8 +25,10 @@ SimGrid (3.0.1) unstable; urgency=low * New: MSG_task_get_source to see on which host a task was generated [HC] GRAS new functionnalities: [MQ] - * enhance the parsing macro to allow the size of multidimentional objects + * Enhance the parsing macro to allow the size of multidimentional objects to be given thru annotations. + * New example (and documentation): Matrix Multiplication a la RPC manner + (as when I was young!) and fix a bunch of bugs found on the way. GRAS performance improvements: [MQ] [DataDesc] diff --git a/configure.ac b/configure.ac index 2b8d5d1fb0..abd71324b3 100644 --- a/configure.ac +++ b/configure.ac @@ -245,6 +245,7 @@ AC_CONFIG_FILES([ examples/gras/timer/Makefile examples/gras/timer/test_sg examples/gras/timer/test_rl examples/gras/chrono/Makefile examples/gras/chrono/test_sg examples/gras/chrono/test_rl examples/gras/tokenS/Makefile examples/gras/tokenS/test_sg examples/gras/tokenS/test_rl + examples/gras/mmrpc/Makefile examples/gras/mmrpc/test_sg examples/gras/mmrpc/test_rl examples/amok/Makefile examples/amok/bandwidth/Makefile examples/amok/bandwidth/test_sg examples/amok/bandwidth/test_rl doc/Makefile @@ -266,6 +267,7 @@ AC_CONFIG_FILES([ examples/gras/timer/test_sg examples/gras/timer/test_rl \ examples/gras/chrono/test_sg examples/gras/chrono/test_rl \ examples/gras/tokenS/test_sg examples/gras/tokenS/test_rl \ + examples/gras/mmrpc/test_sg examples/gras/mmrpc/test_rl \ examples/msg/run_msg_test \ ; do \ test -e $file && chmod +x $file; \ diff --git a/doc/module-gras.doc b/doc/module-gras.doc index adeb57f1f1..a43fec7b1a 100644 --- a/doc/module-gras.doc +++ b/doc/module-gras.doc @@ -49,7 +49,8 @@ There is for now rather few examples of GRAS, but it's better than nothing, isn't it? - - \ref GRAS_ex_ping + - \ref GRAS_ex_ping + - \ref GRAS_ex_mmrpc - \ref GRAS_ex_timer @{ */ @@ -267,7 +268,7 @@ the code of the client and of the server is placed in the same file. See the \ref GRAS_main_generation section if wondering. - \section GRAS_ex_ping_over Overview + \section GRAS_ex_ping_toc Table of contents of the ping example - \ref GRAS_ex_ping_common - \ref GRAS_ex_ping_initial - \ref GRAS_ex_ping_register @@ -297,11 +298,14 @@ This function, called by both the client and the server is in charge of declaring the existing messages to GRAS. Since the payload does not involve any newly created types but only int, this is quite easy. - (to exchange more complicated types, see \ref GRAS_dd) + (to exchange more complicated types, see \ref GRAS_dd or + \ref GRAS_ex_mmrpc for an example). \skip register_messages \until } + [Back to \ref GRAS_ex_ping_toc] + \section GRAS_ex_ping_server 2) Server's code \subsection GRAS_ex_ping_serdata 2.a) The server's globals @@ -325,19 +329,155 @@ \subsection GRAS_ex_ping_sermain 2.c) The "main" of the server This is the "main" of the server. As explained in the \ref - GRAS_main_generation, you don't have to (and shouldn't) write any main() + GRAS_main_generation, you must not write any main() function yourself. Instead, you just have to write a regular function like this one which will act as a main. \skip server \until end_of_server + + [Back to \ref GRAS_ex_ping_toc] \section GRAS_ex_ping_client 3) Client's code \subsection GRAS_ex_ping_climain 3.a) Client's "main" function + This function is quite straightforward, and the inlined comments should + be enough to understand it. + + \skip client + \until end_of_client + + [Back to \ref GRAS_ex_ping_toc] + */ + +--------------------------------------------------------------------- +-------------------------- MM RPC ----------------------------------- +--------------------------------------------------------------------- + +/** \page GRAS_ex_mmrpc A simple RPC for matrix multiplication + +
[\ref GRAS_API]
+ + This example implements a remote matrix multiplication. It involves a client + (creating the matrices and sending the multiplications requests) and a server + (computing the multiplication on client's behalf). + + This example also constitutes a more advanced example of data description + mechanisms, since the message payload type is a bit more complicated than in + other examples such as the ping one (\ref GRAS_ex_ping). + + It works the following way (not very different from the ping example): + - Both the client and the server register all needed messages and datatypes + - The server registers a callback to the "request" message, which computes + what needs to be and returns the result to the expeditor. + - The client creates two matrices, ask for their multiplication and check + the server's answer. + + This example resides in the examples/gras/mmrpc/mmrpc.c file. (See + the \ref GRAS_main_generation section if wondering why both the server + and the client live in the same source file) + + \section GRAS_ex_mmrpc_toc Table of contents of the mmrpc example + - \ref GRAS_ex_mmrpc_common + - \ref GRAS_ex_mmrpc_initial + - \ref GRAS_ex_mmrpc_dataregister + - \ref GRAS_ex_mmrpc_msgregister + - \ref GRAS_ex_mmrpc_server + - \ref GRAS_ex_mmrpc_sercb + - \ref GRAS_ex_mmrpc_sermain + - \ref GRAS_ex_mmrpc_client + - \ref GRAS_ex_mmrpc_climain + +
+ + \dontinclude gras/mmrpc/mmrpc.c + + \section GRAS_ex_mmrpc_common 1) Common code to the client and the server + + \subsection GRAS_ex_mmrpc_initial 1.a) Initial settings + + Let's first load the gras header, specify the matrix size and declare a + logging category (see \ref XBT_log for more info on logging). + + \skip include + \until XBT_LOG + + \subsection GRAS_ex_mmrpc_dataregister 1.b) Register the data types + + The messages involved in this example do use structures as payload, + so we have to declare it to GRAS. Hopefully, this can be done easily by enclosing + the structure declaration within a GRAS_DEFINE macro call. It will then copy this + declaration into an hidden string variable, which can be automatically parsed at + run time. Of course, the declaration is also copied unmodified by this macro, so that it + gets parsed by the compiler also. + + There is some semantic that GRAS cannot guess alone and you need to annotate + your declaration to add some. For example, the ctn pointer can be a reference to an + object or a whole array (in which case you also has to specify its size). This is done + with the GRAS_ANNOTE call. It is removed from the text passed to the compiler, but it helps + GRAS getting some information about the semantic of your data. Here, it says that \a ctn is an + array, which size is the result of the operation \a rows * \a cols (with \a rows and \a cols + being the other fields of the structure). + + Please note that this annotation mechanism is not as robust and cool as this example seems to + imply. If you want to use it yourself, you'd better use the exact right syntax, which is + detailed in the \ref GRAS_dd section. + + \skip GRAS_DEFINE + \until matrix_t + + \subsection GRAS_ex_mmrpc_msgregister 1.c) Register the messages + + This function, called by both the client and the server is in charge of + declaring the existing messages to GRAS. Note the use of the \ref gras_datadesc_by_symbol + function to parse and retrieve the structure declaration which were passed to \ref GRAS_DEFINE + above. + + The datatype description builded that way can then be used to build an array datatype or + to declare messages. + + \skip register_messages + \until } + + [Back to \ref GRAS_ex_mmrpc_toc] + + \section GRAS_ex_mmrpc_server 2) Server's code + + \subsection GRAS_ex_mmrpc_sercb 2.a) The callback to the mmrpc message + + Here is the callback run when the server receives any mmrpc message (this + will be registered later by the server). Note the way we get the message + payload. In the ping example, there was one additional level of pointer + indirection (see \ref GRAS_ex_ping_sercb). This is because the payload is + an array here (ie a pointer) whereas it is a scalar in the ping example. + + \skip server_cb_request_handler + \until end_of_server_cb_request_handler + + \subsection GRAS_ex_mmrpc_sermain 2.b) The "main" of the server + + This is the "main" of the server. As explained in the \ref + GRAS_main_generation, you must not write any main() + function yourself. Instead, you just have to write a regular function + like this one which will act as a main. + + \skip server + \until end_of_server + + [Back to \ref GRAS_ex_mmrpc_toc] + + \section GRAS_ex_mmrpc_client 3) Client's code + + \subsection GRAS_ex_mmrpc_climain 3.a) Client's "main" function + + This function is quite straightforward, and the inlined comments should + be enough to understand it. + \skip client \until end_of_client + + [Back to \ref GRAS_ex_mmrpc_toc] */ --------------------------------------------------------------------- diff --git a/examples/gras/Makefile.am b/examples/gras/Makefile.am index 08dea3b8fc..20598c2456 100644 --- a/examples/gras/Makefile.am +++ b/examples/gras/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS= ping timer chrono tokenS +SUBDIRS= ping timer chrono tokenS mmrpc include $(top_srcdir)/acmacro/dist-files.mk diff --git a/examples/gras/mmrpc/.cvsignore b/examples/gras/mmrpc/.cvsignore new file mode 100644 index 0000000000..3fe84b0062 --- /dev/null +++ b/examples/gras/mmrpc/.cvsignore @@ -0,0 +1,8 @@ +.deps .libs Makefile Makefile.in _*.c mmrpc_server mmrpc_client mmrpc_simulator +test_sg +test_rl +mmrpc.Makefile.am +mmrpc.Makefile.local +mmrpc.Makefile.remote +mmrpc.deploy.sh +mmrpc.trace diff --git a/examples/gras/mmrpc/Makefile.am b/examples/gras/mmrpc/Makefile.am new file mode 100644 index 0000000000..46d20142ae --- /dev/null +++ b/examples/gras/mmrpc/Makefile.am @@ -0,0 +1,23 @@ +INCLUDES= -I$(top_srcdir)/include +TESTS= test_rl test_sg +EXTRA_DIST=mmrpc_deployment.xml $(TESTS) + +# AUTOMAKE variable definition +noinst_PROGRAMS=mmrpc_client mmrpc_server mmrpc_simulator + +mmrpc_simulator_SOURCES= _mmrpc_simulator.c mmrpc.c +mmrpc_simulator_LDADD= $(top_builddir)/src/libsimgrid.la + +mmrpc_client_SOURCES= _mmrpc_client.c mmrpc.c +mmrpc_client_LDADD= $(top_builddir)/src/libgras.la + +mmrpc_server_SOURCES= _mmrpc_server.c mmrpc.c +mmrpc_server_LDADD= $(top_builddir)/src/libgras.la + +# Take care of generatated sources +NAME=mmrpc +PROCESSES= client server +include $(top_srcdir)/examples/temps-gras-stub.mk + +# Cruft +include $(top_srcdir)/acmacro/dist-files.mk diff --git a/examples/gras/mmrpc/mmrpc.c b/examples/gras/mmrpc/mmrpc.c new file mode 100644 index 0000000000..b64153b01f --- /dev/null +++ b/examples/gras/mmrpc/mmrpc.c @@ -0,0 +1,213 @@ +/* $Id$ */ + +/* GridRPC - Fake Grid RPC thingy doing matrix multiplications (as expected)*/ + +/* Copyright (c) 2005 Martin Quinson. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "gras.h" + +#define MATSIZE 128 + +XBT_LOG_NEW_DEFAULT_CATEGORY(MatMult,"Messages specific to this example"); + +GRAS_DEFINE_TYPE(s_matrix, +struct s_matrix { + int rows; + int cols; + double *ctn GRAS_ANNOTE(size, rows*cols); +};); +typedef struct s_matrix matrix_t; + +static void mat_dump(matrix_t *mat, const char* name) { + int i,j; + + printf(">>> Matrix %s dump (%d x %d)\n",name,mat->rows,mat->cols); + for (i=0; irows; i++) { + printf(" "); + for (j=0; jcols; j++) + printf(" %.2f",mat->ctn[i*mat->cols + j]); + printf("\n"); + } + printf("<<< end of matrix %s dump\n",name); +} + +/* register messages which may be sent and their payload + (common to client and server) */ +static void register_messages(void) { + gras_datadesc_type_t matrix_type, request_type; + + matrix_type=gras_datadesc_by_symbol(s_matrix); + request_type=gras_datadesc_array_fixed("matrix_t[2]",matrix_type,2); + + gras_msgtype_declare("answer", matrix_type); + gras_msgtype_declare("request", request_type); +} + +/* Function prototypes */ +int server (int argc,char *argv[]); +int client (int argc,char *argv[]); + +/* ********************************************************************** + * Server code + * **********************************************************************/ + +static int server_cb_request_handler(gras_socket_t expeditor, void *payload_data) { + + /* 1. Get the payload into the data variable */ + matrix_t *data=(matrix_t*)payload_data; + matrix_t result; + int i,j,k; + + /* 2. Make some room to return the result */ + result.rows = data[0].rows; + result.cols = data[1].cols; + result.ctn = xbt_malloc0(sizeof(double) * result.rows * result.cols); + + /* 3. Do the computation */ + for (i=0; i>>>>>>> Connected to server which is on %s:%d <<<<<<<<", + gras_socket_peer_name(toserver),gras_socket_peer_port(toserver)); + + /* 7. Prepare and send the request to the server */ + + request[0].rows=request[0].cols=request[1].rows=request[1].cols=MATSIZE; + + request[0].ctn=xbt_malloc0(sizeof(double)*MATSIZE*MATSIZE); + request[1].ctn=xbt_malloc0(sizeof(double)*MATSIZE*MATSIZE); + + for (i=0; i>>>>>>> Request sent to %s:%d <<<<<<<<", + gras_socket_peer_name(toserver),gras_socket_peer_port(toserver)); + + /* 8. Wait for the answer from the server, and deal with issues */ + gras_msg_wait(6000,gras_msgtype_by_name("answer"),&from,&answer); + + // mat_dump(&answer,"C:answer"); + for (i=0; i>>>>>>> Got answer from %s:%d <<<<<<<<", + gras_socket_peer_name(from),gras_socket_peer_port(from)); + + /* 10. Free the allocated resources, and shut GRAS down */ + gras_socket_close(toserver); + gras_exit(); + INFO0("Done."); + return 0; +} /* end_of_client */ diff --git a/examples/gras/mmrpc/mmrpc_deployment.xml b/examples/gras/mmrpc/mmrpc_deployment.xml new file mode 100644 index 0000000000..78dc211348 --- /dev/null +++ b/examples/gras/mmrpc/mmrpc_deployment.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/gras/mmrpc/test_rl.in b/examples/gras/mmrpc/test_rl.in new file mode 100755 index 0000000000..75d74cf419 --- /dev/null +++ b/examples/gras/mmrpc/test_rl.in @@ -0,0 +1,11 @@ +#! @BASH@ -e +if [ x@EXEEXT@ = x ] ; then +# exenv="libtool --mode=execute valgrind --show-reachable=yes --run-libc-freeres=no " + exenv=$SG_TEST_EXENV +else + exenv=wine +fi + +$exenv ./mmrpc_server@EXEEXT@ 4002 $@ & +sleep 1 +$exenv ./mmrpc_client@EXEEXT@ 127.0.0.1 4002 $@ diff --git a/examples/gras/mmrpc/test_sg.in b/examples/gras/mmrpc/test_sg.in new file mode 100755 index 0000000000..454c24322a --- /dev/null +++ b/examples/gras/mmrpc/test_sg.in @@ -0,0 +1,9 @@ +#! @BASH@ +if [ x@EXEEXT@ = x ] ; then + exenv=$SG_TEST_EXENV +else + exenv=wine +fi + +exec $exenv ./mmrpc_simulator@EXEEXT@ @top_srcdir@/examples/msg/small_platform.xml @srcdir@/mmrpc_deployment.xml $@ + -- 2.20.1