--- music-1.0.7.orig/debian/changelog +++ music-1.0.7/debian/changelog @@ -0,0 +1,66 @@ +music (1.0.7-1.2ubuntu2) xenial; urgency=medium + + * No-change rebuild for openmpi transition. + + -- Matthias Klose Sun, 07 Feb 2016 12:56:57 +0000 + +music (1.0.7-1.2ubuntu1) wily; urgency=medium + + * Rename library packages for g++5 ABI transition. + + -- Iain Lane Tue, 04 Aug 2015 11:31:21 +0100 + +music (1.0.7-1.2build1) trusty; urgency=medium + + * No-change rebuild for libopenmpi1.3 -> libopenmpi1.6 transition. + + -- Logan Rosen Sat, 14 Dec 2013 23:01:08 -0500 + +music (1.0.7-1.2) unstable; urgency=low + + * Non-maintainer upload. + * Fix ftbfs with GCC-4.7: add "#include " to + utils/VisualiseNeurons.cpp (Closes: #667291). + + -- Mònica Ramírez Arceda Thu, 10 May 2012 13:40:31 +0200 + +music (1.0.7-1.1) unstable; urgency=low + + * Non-maintainer upload. + * Stop shipping .la files (Closes: #622439). + + -- Luk Claes Mon, 06 Jun 2011 08:01:00 +0200 + +music (1.0.7-1) unstable; urgency=high + + * Upstream release 1.0.7 (containing urgent bugfix). + * Updated standards version to 3.9.0. + * Added missing ${misc:Depends} field for libmusic-dev. + + -- Mikael Djurfeldt Wed, 28 Jul 2010 04:24:40 +0200 + +music (1.0.6-1) unstable; urgency=low + + * Upstream release 1.0.6. + + -- Mikael Djurfeldt Sun, 25 Oct 2009 12:20:08 +0100 + +music (1.0.5-1) unstable; urgency=low + + * Upstream release 1.0.5 (Closes: #524032, #526662). + + -- Mikael Djurfeldt Sat, 24 Oct 2009 10:41:37 +0200 + +music (1.0.4-1) unstable; urgency=low + + * Upstream release 1.0.4. + * Temporarily added a build dependency on libibverbs-dev (until a + dependency bug in libopenmpi-dev is fixed). + + -- Mikael Djurfeldt Wed, 01 Apr 2009 11:14:58 +0200 + +music (1.0.3-1) unstable; urgency=low + + * Initial Release (Closes: #518538, #518541, #518542, #518543, #518544) + + -- Mikael Djurfeldt Fri, 13 Mar 2009 11:30:35 +0100 --- music-1.0.7.orig/debian/compat +++ music-1.0.7/debian/compat @@ -0,0 +1 @@ +7 --- music-1.0.7.orig/debian/control +++ music-1.0.7/debian/control @@ -0,0 +1,63 @@ +Source: music +Priority: extra +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Mikael Djurfeldt +Build-Depends: debhelper (>= 7), autotools-dev, autoconf, automake, libtool, libopenmpi-dev, libibverbs-dev, freeglut3-dev, texlive-latex-base, texlive-latex-extra, asymptote, chrpath +Standards-Version: 3.9.0 +Section: libs +Homepage: http://software.incf.org/software/music/home + +Package: libmusic-dev +Section: libdevel +Architecture: any +Depends: libmusic1v5 (= ${binary:Version}), ${misc:Depends} +Description: Multi-Simulation Coordinator for MPI -- Development files + MUSIC allows spike events and continuous time series to be + communicated between parallel applications within the same MPI job in + a cluster computer. Typical usage cases are connecting models + developed for different simulators and connecting a parallel + simulator to a post-processing tool. + . + This package contains the header files which are needed to compile + and link programs against libmusic. + +Package: libmusic1v5 +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Conflicts: libmusic1 +Replaces: libmusic1 +Description: Multi-Simulation Coordinator for MPI -- Runtime library + MUSIC allows spike events and continuous time series to be + communicated between parallel applications within the same MPI job in + a cluster computer. Typical usage cases are connecting models + developed for different simulators and connecting a parallel + simulator to a post-processing tool. + . + This package contains the MUSIC library. + +Package: music-bin +Section: science +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Multi-Simulation Coordinator for MPI -- Utilities + MUSIC allows spike events and continuous time series to be + communicated between parallel applications within the same MPI job in + a cluster computer. Typical usage cases are connecting models + developed for different simulators and connecting a parallel + simulator to a post-processing tool. + . + This package contains the MUSIC launch utility. + +Package: music-doc +Section: doc +Architecture: all +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Multi-Simulation Coordinator for MPI -- Manual + MUSIC allows spike events and continuous time series to be + communicated between parallel applications within the same MPI job in + a cluster computer. Typical usage cases are connecting models + developed for different simulators and connecting a parallel + simulator to a post-processing tool. + . + This package contains the MUSIC manual. --- music-1.0.7.orig/debian/copyright +++ music-1.0.7/debian/copyright @@ -0,0 +1,37 @@ +Author(s): + + Mikael Djurfeldt + Örjan Ekeberg + +Copyright: + + Copyright (C) 2007-2009 INCF + +License: + + MUSIC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + MUSIC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + + +Files in subdirectory rudeconfig have copyright: + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + GNU GENERAL PUBLIC LICENSE Version 2, June 1991 + + +File src/music/interval_tree.hh has copyright: + Copyright (C) 2008, 2009 Mikael Djurfeldt + GNU GENERAL PUBLIC LICENSE Version 3 --- music-1.0.7.orig/debian/docs +++ music-1.0.7/debian/docs @@ -0,0 +1,4 @@ +AUTHORS +README +NEWS +BUGS --- music-1.0.7.orig/debian/libmusic-dev.dirs +++ music-1.0.7/debian/libmusic-dev.dirs @@ -0,0 +1,3 @@ +usr/lib +usr/include +usr/share/doc/libmusic-dev/examples --- music-1.0.7.orig/debian/libmusic-dev.docs +++ music-1.0.7/debian/libmusic-dev.docs @@ -0,0 +1,4 @@ +AUTHORS +README +NEWS +BUGS --- music-1.0.7.orig/debian/libmusic-dev.install +++ music-1.0.7/debian/libmusic-dev.install @@ -0,0 +1,3 @@ +usr/include/* +usr/lib/lib*.a +usr/lib/lib*.so --- music-1.0.7.orig/debian/libmusic1v5.dirs +++ music-1.0.7/debian/libmusic1v5.dirs @@ -0,0 +1 @@ +usr/lib --- music-1.0.7.orig/debian/libmusic1v5.docs +++ music-1.0.7/debian/libmusic1v5.docs @@ -0,0 +1,4 @@ +AUTHORS +README +NEWS +BUGS --- music-1.0.7.orig/debian/libmusic1v5.install +++ music-1.0.7/debian/libmusic1v5.install @@ -0,0 +1 @@ +usr/lib/lib*.so.* --- music-1.0.7.orig/debian/libmusic1v5.lintian-overrides +++ music-1.0.7/debian/libmusic1v5.lintian-overrides @@ -0,0 +1,2 @@ +# G++5 ABI transition +libmusic1v5: package-name-doesnt-match-sonames libmusic1 --- music-1.0.7.orig/debian/music-bin.dirs +++ music-1.0.7/debian/music-bin.dirs @@ -0,0 +1 @@ +usr/bin --- music-1.0.7.orig/debian/music-bin.docs +++ music-1.0.7/debian/music-bin.docs @@ -0,0 +1,3 @@ +AUTHORS +README +NEWS --- music-1.0.7.orig/debian/music-bin.install +++ music-1.0.7/debian/music-bin.install @@ -0,0 +1,2 @@ +usr/bin/* +usr/share/man/man1/* --- music-1.0.7.orig/debian/music-doc.dirs +++ music-1.0.7/debian/music-doc.dirs @@ -0,0 +1 @@ +usr/share/doc/music-doc --- music-1.0.7.orig/debian/music-doc.doc-base +++ music-1.0.7/debian/music-doc.doc-base @@ -0,0 +1,16 @@ +Document: music-manual +Title: MUSIC Manual +Author: Örjan Ekeberg and Mikael Djurfeldt +Abstract: MUSIC is an API allowing large scale neuron simulators using MPI + internally to exchange data during runtime. MUSIC provides + mechanisms to transfer massive amounts of event information and + continuous values from one parallel application to another. Special + care has been taken to ensure that existing simulators can be + adapted to MUSIC. In particular, MUSIC handles data transfer + between applications that use different time steps and different + data allocation strategies. +Section: Science/Biology + +Format: PDF +Files: /usr/share/doc/music-doc/music-manual.pdf.gz + --- music-1.0.7.orig/debian/music-doc.docs +++ music-1.0.7/debian/music-doc.docs @@ -0,0 +1,4 @@ +AUTHORS +README +NEWS +doc/music-manual.pdf --- music-1.0.7.orig/debian/rules +++ music-1.0.7/debian/rules @@ -0,0 +1,116 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) +CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) +else +CROSS= --build $(DEB_BUILD_GNU_TYPE) +endif + + + + +# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so +version=`ls src/.libs/lib*.so.* | \ + awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` +major=`ls src/.libs/lib*.so.* | \ + awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` + +config.status: configure + dh_testdir + +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + ./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info + + +build: build-stamp +build-stamp: config.status + dh_testdir + + $(MAKE) + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + [ ! -f Makefile ] || $(MAKE) distclean + rm -f config.sub config.guess + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + +# Remove rpaths in libraries and binaries + ( cd $(CURDIR)/debian/tmp/usr/lib; chrpath -d libmusic.so libmusic-c.so ) + ( cd $(CURDIR)/debian/tmp/usr/bin; chrpath -d eventcounter eventgenerator eventlogger eventselect eventsink eventsource music viewevents ) + +# Build manual +# ( cd $(CURDIR)/doc; make music-manual.pdf ) + +# Fill up examples directory + ( cd $(CURDIR)/test; cp -p README clocksource.cc contsink.cc constsource.cc eventdelay.cc contdelay.cc waveproducer.cc waveconsumer.cc messagesource.cc *.music *.data *.dat $(CURDIR)/debian/libmusic-dev/usr/share/doc/libmusic-dev/examples/ ) + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples + dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install --- music-1.0.7.orig/doc/figures/dataconvergence.asy +++ music-1.0.7/doc/figures/dataconvergence.asy @@ -0,0 +1,21 @@ +unitsize(10mm); + +pair p1=(1,2); +pair p2=(6,2.1); + +void application(int n, pair pos) { + for (int i=n-1; i>=0; --i) { + filldraw(box(pos-(1,1)+i*(0.1, 0.1), pos+(1,1)+i*(0.1, 0.1)), + lightgray, black); + } +} + +application(5, p1); + +draw("2.6\,Tb/s", p1+(1.2,0.2){right}..{right}p2+(-0.9,0.1), black+1, Arrow); +draw("2.6\,Gb/s", p2+(1.2,0.1){right}..{right}p2+(3.2,0.1), black+1, Arrow); + +application(3, p2); + +label("Simulator", p1); +label("EEG", p2); --- music-1.0.7.orig/doc/figures/datamapping.asy +++ music-1.0.7/doc/figures/datamapping.asy @@ -0,0 +1,56 @@ +unitsize(10mm); + +label(scale(1.5)*"Sender", (1.5, 10.5)); +label(scale(1.5)*"Receiver", (11.5, 10.5)); + +fill(box((2,0), (3,10)), gray(0.8)); +draw(box((0,0), (3,10))); + +fill(box((10,0), (11,10)), gray(0.8)); +draw(box((10,0), (13,10))); + +// Sender arrows +for (real y=0.75; y<9.6; y+=0.5) + draw((1.0,y)--(2.0,y), gray(0.5), Arrow); + +// Sender data array +filldraw(box((0.5,0.5),(1.0,9.5)), gray(0.9), black); +for (real y=0.5; y<9.6; y+=0.5) + draw((0.5,y)--(1.0,y)); + +label(rotate(90)*"Distributed sender data", (0.26, 5.0)); + +// Receiver arrows +for (real y=0.75; y<9.6; y+=0.5) + draw((11.0,y)--(12.0,y), gray(0.5), Arrow); + +// Receiver data array +filldraw(box((12.0,0.5),(12.5,9.5)), gray(0.9), black); +for (real y=0.5; y<9.6; y+=0.5) + draw((12.0,y)--(12.5,y)); + +label(rotate(-90)*"Distributed receiver data", (12.74, 5.0)); + +draw((-0.2,2.5)--(3.2,2.5), dashed); +draw((-0.2,5.0)--(3.2,5.0), dashed); +draw((-0.2,7.5)--(3.2,7.5), dashed); + +draw((9.8,3.5)--(13.2,3.5), dashed); +draw((9.8,6.5)--(13.2,6.5), dashed); + +// Fan-in +draw((3,0.5){right}..tension 1.5 ..{right}(5.5,5.0)); +draw((3,2.5){right}..{right}(5.5,5.0)); +draw((3,5.0){right}..{right}(5.5,5.0)); +draw((3,7.5){right}..{right}(5.5,5.0)); +draw((3,9.5){right}..tension 1.5 ..{right}(5.5,5.0)); + +// Fan-out +draw((7.5,5.0){right}..tension 1.5 ..{right}(10,0.5)); +draw((7.5,5.0){right}..{right}(10,3.5)); +draw((7.5,5.0){right}..{right}(10,6.5)); +draw((7.5,5.0){right}..tension 1.5 ..{right}(10,9.5)); + +draw((5.4,5.0)--(7.6,5.0), black+1, Arrow(position=0.8)); +draw((5.5, 4.5)--(6.0,5.5)); +label("Width", (6.0, 6.0)); --- music-1.0.7.orig/doc/figures/messysim.asy +++ music-1.0.7/doc/figures/messysim.asy @@ -0,0 +1,103 @@ +unitsize(10mm); + +pair p11=(2,3); +pair p12=(1.5,2.5); +pair p13=(1,2); + +pair p21=(6,2); +pair p22=(6.5,1.5); +pair p23=(7,1); + +pair p31=(5,5); +pair p32=(5.3,5.1); +pair p33=(5.6,5.2); +pair p34=(5.9,5.3); +pair p35=(6.2,5.4); + +void application(pair pos) { + filldraw(box(pos-(1,1), pos+(1,1)), lightgray, black); +} + +void flow(pair a, pair adir, int aoffs, + pair b, pair bdir, int boffs) { + pair ao = (adir.y, -adir.x)*0.1*aoffs; + pair bo = (-bdir.y, bdir.x)*0.1*boffs; + draw(a+adir+ao{adir}..{-bdir}b+bdir+bo, black, Arrow); +} + + +application(p11); +application(p12); +application(p13); + +application(p21); +application(p22); +application(p23); + +application(p31); +application(p32); +application(p33); +application(p34); +application(p35); + +flow(p11, E, -2, p21, W, -2); +flow(p11, E, 0, p22, W, -2); +flow(p11, E, 2, p23, W, -2); +flow(p12, E, -2, p21, W, 0); +flow(p12, E, 0, p22, W, 0); +flow(p12, E, 2, p23, W, 0); +flow(p13, E, -2, p21, W, 2); +flow(p13, E, 0, p22, W, 2); +flow(p13, E, 2, p23, W, 2); + +flow(p11, N, -4, p31, W, -2); +flow(p11, N, -2, p32, W, -2); +flow(p11, N, 0, p33, W, -2); +flow(p11, N, 2, p34, W, -2); +flow(p11, N, 4, p35, W, -2); +flow(p12, N, -4, p31, W, 0); +flow(p12, N, -2, p32, W, 0); +flow(p12, N, 0, p33, W, 0); +flow(p12, N, 2, p34, W, 0); +flow(p12, N, 4, p35, W, 0); +flow(p13, N, -4, p31, W, 2); +flow(p13, N, -2, p32, W, 2); +flow(p13, N, 0, p33, W, 2); +flow(p13, N, 2, p34, W, 2); +flow(p13, N, 4, p35, W, 2); + +flow(p21, N, 3, p31, S, 2); +flow(p21, N, 4, p32, S, 2); +flow(p21, N, 5, p33, S, 2); +flow(p21, N, 6, p34, S, 2); +flow(p21, N, 7, p35, S, 2); +flow(p22, N, 3, p31, S, 4); +flow(p22, N, 4, p32, S, 4); +flow(p22, N, 5, p33, S, 4); +flow(p22, N, 6, p34, S, 4); +flow(p22, N, 7, p35, S, 4); +flow(p23, N, 3, p31, S, 6); +flow(p23, N, 4, p32, S, 6); +flow(p23, N, 5, p33, S, 6); +flow(p23, N, 6, p34, S, 6); +flow(p23, N, 7, p35, S, 6); + +flow(p31, S, 2, p21, N, 8); +flow(p31, S, 4, p22, N, 8); +flow(p31, S, 6, p23, N, 8); +flow(p32, S, 2, p21, N, 6); +flow(p32, S, 4, p22, N, 6); +flow(p32, S, 6, p23, N, 6); +flow(p33, S, 2, p21, N, 4); +flow(p33, S, 4, p22, N, 4); +flow(p33, S, 6, p23, N, 4); +flow(p34, S, 2, p21, N, 2); +flow(p34, S, 4, p22, N, 2); +flow(p34, S, 6, p23, N, 2); +flow(p35, S, 2, p21, N, 0); +flow(p35, S, 4, p22, N, 0); +flow(p35, S, 6, p23, N, 0); + +label("LGN", p13); +label("NEST", p23); +label("Neuron", p35); --- music-1.0.7.orig/doc/figures/messysimABC.asy +++ music-1.0.7/doc/figures/messysimABC.asy @@ -0,0 +1,103 @@ +unitsize(10mm); + +pair p11=(2,3); +pair p12=(1.5,2.5); +pair p13=(1,2); + +pair p21=(6,2); +pair p22=(6.5,1.5); +pair p23=(7,1); + +pair p31=(5,5); +pair p32=(5.3,5.1); +pair p33=(5.6,5.2); +pair p34=(5.9,5.3); +pair p35=(6.2,5.4); + +void application(pair pos) { + filldraw(box(pos-(1,1), pos+(1,1)), lightgray, black); +} + +void flow(pair a, pair adir, int aoffs, + pair b, pair bdir, int boffs) { + pair ao = (adir.y, -adir.x)*0.1*aoffs; + pair bo = (-bdir.y, bdir.x)*0.1*boffs; + draw(a+adir+ao{adir}..{-bdir}b+bdir+bo, black, Arrow); +} + + +application(p11); +application(p12); +application(p13); + +application(p21); +application(p22); +application(p23); + +application(p31); +application(p32); +application(p33); +application(p34); +application(p35); + +flow(p11, E, -2, p21, W, -2); +flow(p11, E, 0, p22, W, -2); +flow(p11, E, 2, p23, W, -2); +flow(p12, E, -2, p21, W, 0); +flow(p12, E, 0, p22, W, 0); +flow(p12, E, 2, p23, W, 0); +flow(p13, E, -2, p21, W, 2); +flow(p13, E, 0, p22, W, 2); +flow(p13, E, 2, p23, W, 2); + +flow(p11, N, -4, p31, W, -2); +flow(p11, N, -2, p32, W, -2); +flow(p11, N, 0, p33, W, -2); +flow(p11, N, 2, p34, W, -2); +flow(p11, N, 4, p35, W, -2); +flow(p12, N, -4, p31, W, 0); +flow(p12, N, -2, p32, W, 0); +flow(p12, N, 0, p33, W, 0); +flow(p12, N, 2, p34, W, 0); +flow(p12, N, 4, p35, W, 0); +flow(p13, N, -4, p31, W, 2); +flow(p13, N, -2, p32, W, 2); +flow(p13, N, 0, p33, W, 2); +flow(p13, N, 2, p34, W, 2); +flow(p13, N, 4, p35, W, 2); + +flow(p21, N, 3, p31, S, 2); +flow(p21, N, 4, p32, S, 2); +flow(p21, N, 5, p33, S, 2); +flow(p21, N, 6, p34, S, 2); +flow(p21, N, 7, p35, S, 2); +flow(p22, N, 3, p31, S, 4); +flow(p22, N, 4, p32, S, 4); +flow(p22, N, 5, p33, S, 4); +flow(p22, N, 6, p34, S, 4); +flow(p22, N, 7, p35, S, 4); +flow(p23, N, 3, p31, S, 6); +flow(p23, N, 4, p32, S, 6); +flow(p23, N, 5, p33, S, 6); +flow(p23, N, 6, p34, S, 6); +flow(p23, N, 7, p35, S, 6); + +flow(p31, S, 2, p21, N, 8); +flow(p31, S, 4, p22, N, 8); +flow(p31, S, 6, p23, N, 8); +flow(p32, S, 2, p21, N, 6); +flow(p32, S, 4, p22, N, 6); +flow(p32, S, 6, p23, N, 6); +flow(p33, S, 2, p21, N, 4); +flow(p33, S, 4, p22, N, 4); +flow(p33, S, 6, p23, N, 4); +flow(p34, S, 2, p21, N, 2); +flow(p34, S, 4, p22, N, 2); +flow(p34, S, 6, p23, N, 2); +flow(p35, S, 2, p21, N, 0); +flow(p35, S, 4, p22, N, 0); +flow(p35, S, 6, p23, N, 0); + +label("Appl. A", p13); +label("Appl. B", p23); +label("Appl. C", p35); --- music-1.0.7.orig/doc/figures/multisim.asy +++ music-1.0.7/doc/figures/multisim.asy @@ -0,0 +1,30 @@ +unitsize(10mm); + +pair p1=(1,2); +pair p2=(6,1); +pair p3=(5,5); + +void application(int n, pair pos) { + for (int i=n-1; i>=0; --i) { + filldraw(box(pos-(1,1)+i*(0.1, 0.1), pos+(1,1)+i*(0.1, 0.1)), + lightgray, black); + } +} + +application(5, p1); + +draw(p1+(0.2,1.2){up}..{right}p3+(-0.9,0.1), black+1, Arrow); +draw(p1+(1.2,0.2){right}..{right}p2+(-0.9,0.1), black+1, Arrow); + +application(3, p2); + +pair d=(0.3,0); + +draw(p3+(0.1,-0.9)-d{down}..{down}p2+(0.1,1.1)-d, black+1, Arrow); +draw(p2+(0.1,1.1)+d{up}..{up}p3+(0.1,-0.9)+d, black+1, Arrow); + +application(3, p3); + +label("Appl. $A$", p1); +label("Appl. $B$", p2); +label("Appl. $C$", p3); --- music-1.0.7.orig/doc/figures/receiverport.asy +++ music-1.0.7/doc/figures/receiverport.asy @@ -0,0 +1,22 @@ +unitsize(10mm); + +fill(box((10,0), (11,10)), gray(0.8)); +draw(box((10,0), (13,10))); + +// Receiver arrows +for (real y=0.75; y<9.6; y+=0.5) + draw((11.0,y)--(12.0,y), gray(0.5), Arrow); + +// Receiver data array +filldraw(box((12.0,0.5),(12.5,9.5)), gray(0.9), black); +for (real y=0.5; y<9.6; y+=0.5) + draw((12.0,y)--(12.5,y)); + +label(rotate(-90)*"Distributed receiver data", (12.74, 5.0)); + +draw((9.8,3.5)--(13.2,3.5), dashed); +draw((9.8,6.5)--(13.2,6.5), dashed); + +// Port +filldraw(box((9.5,0.5),(10.0,9.5)), white, black); +label(rotate(-90)*"Input Port", (9.74, 5.0)); --- music-1.0.7.orig/doc/figures/remapping.asy +++ music-1.0.7/doc/figures/remapping.asy @@ -0,0 +1,46 @@ +unitsize(10mm); + +real[] prm = {5, 8, 0, 2, 9, 7, 4, 3, 6, 12, 13, 11, 15, 1, 10, 17, 14, 16}; + +label(scale(1.5)*"Sender", (1.5, 10.5)); +label(scale(1.5)*"Receiver", (7.5, 10.5)); + +filldraw(box((0,0), (3,10)), gray(0.9), black); + +filldraw(box((5,0), (10,10)), gray(0.9), black); + +// Sender arrows +for (real y=0.75; y<9.6; y+=0.5) { + draw((1.0,y)--(2.0,y), gray(0.5), Arrow); + draw((2.5,y)--(5.5,y), gray(0.5), Arrow); + + // Sender neurons + filldraw(circle((1.0,y), 0.2), gray(0.5), black); + + // Reveiver neurons + filldraw(circle((9.0,y), 0.2), gray(0.5), black); +} + +// Sender data array +filldraw(box((2.0,0.5),(2.5,9.5)), gray(0.7), black); +for (real y=0.5; y<9.6; y+=0.5) { + draw((2.0,y)--(2.5,y)); +} + +// Receiver data array +filldraw(box((5.5,0.5),(6,9.5)), gray(0.7), black); +for (real y=0.5; y<9.6; y+=0.5) { + draw((5.5,y)--(6,y)); +} + +// Remapping arrows +for (int i=0; i<18; ++i) + draw((6,0.75+i*0.5){right}..{right}(8.8,0.75+prm[i]*0.5), Arrow); + +// Indicate processor borders +draw((-0.2,2.5)--(3.2,2.5), dashed); +draw((-0.2,5.0)--(3.2,5.0), dashed); +draw((-0.2,7.5)--(3.2,7.5), dashed); + +draw((4.8,3.5)--(10.2,3.5), dashed); +draw((4.8,6.5)--(10.2,6.5), dashed); --- music-1.0.7.orig/doc/figures/remapping2.asy +++ music-1.0.7/doc/figures/remapping2.asy @@ -0,0 +1,46 @@ +unitsize(10mm); + +real[] prm = {5, 8, 0, 2, 9, 7, 4, 3, 6, 12, 13, 11, 15, 1, 10, 17, 14, 16}; + +label(scale(1.5)*"Sender", (1.5, 10.5)); +label(scale(1.5)*"Receiver", (7.5, 10.5)); + +filldraw(box((0,0), (3,10)), gray(0.9), black); + +filldraw(box((5,0), (10,10)), gray(0.9), black); + +// Sender arrows +for (real y=0.75; y<9.6; y+=0.5) { + draw((1.0,y)--(2.0,y), gray(0.5), Arrow); + draw((5.5,y)--(8.8,y), gray(0.5), Arrow); + + // Sender neurons + filldraw(circle((1.0,y), 0.2), gray(0.5), black); + + // Reveiver neurons + filldraw(circle((9.0,y), 0.2), gray(0.5), black); +} + +// Sender data array +filldraw(box((2.0,0.5),(2.5,9.5)), gray(0.7), black); +for (real y=0.5; y<9.6; y+=0.5) { + draw((2.0,y)--(2.5,y)); +} + +// Receiver data array +filldraw(box((5.5,0.5),(6,9.5)), gray(0.7), black); +for (real y=0.5; y<9.6; y+=0.5) { + draw((5.5,y)--(6,y)); +} + +// Remapping arrows +for (int i=0; i<18; ++i) + draw((2.5,0.75+i*0.5){right}..{right}(5.5,0.75+prm[i]*0.5), Arrow); + +// Indicate processor borders +draw((-0.2,2.5)--(3.2,2.5), dashed); +draw((-0.2,5.0)--(3.2,5.0), dashed); +draw((-0.2,7.5)--(3.2,7.5), dashed); + +draw((4.8,3.5)--(10.2,3.5), dashed); +draw((4.8,6.5)--(10.2,6.5), dashed); --- music-1.0.7.orig/doc/figures/senderport.asy +++ music-1.0.7/doc/figures/senderport.asy @@ -0,0 +1,23 @@ +unitsize(10mm); + +fill(box((2,0), (3,10)), gray(0.8)); +draw(box((0,0), (3,10))); + +// Sender arrows +for (real y=0.75; y<9.6; y+=0.5) + draw((1.0,y)--(2.0,y), gray(0.5), Arrow); + +// Sender data array +filldraw(box((0.5,0.5),(1.0,9.5)), gray(0.9), black); +for (real y=0.5; y<9.6; y+=0.5) + draw((0.5,y)--(1.0,y)); + +label(rotate(90)*"Distributed sender data", (0.26, 5.0)); + +draw((-0.2,2.5)--(3.2,2.5), dashed); +draw((-0.2,5.0)--(3.2,5.0), dashed); +draw((-0.2,7.5)--(3.2,7.5), dashed); + +// Port +filldraw(box((3.0,0.5),(3.5,9.5)), white, black); +label(rotate(90)*"Output Port", (3.24, 5.0)); --- music-1.0.7.orig/doc/figures/ticklogic.asy +++ music-1.0.7/doc/figures/ticklogic.asy @@ -0,0 +1,39 @@ +import markers; + +unitsize(10mm); + +label("Sender", (5, 8.5)); +label("MUSIC", (0, 3), NE); +label("MPI", (0, 4.5), NE); +label("Receiver", (5, 1.5)); + +draw(box((10,8), (0,9)), dashed); +filldraw(box((10,3), (0,7)), gray(0.8), dotted); +draw(box((10,1), (0,2)), dashed); +filldraw(box((10,5.5), (0,4.5)), gray(0.5)); + +draw("Simulated Time", (0,0)--(10,0), Arrow); + +// Senders ticks +int i=1; +for (real t=1; t<10; t+=2, ++i) + draw(format("$s_{%d}$", i), (t, 8)--(t, 7), Arrow); + +// Receivers ticks +int i=1; +for (real t=2.5; t<10; t+=5, ++i) + draw(format("$r_{%d}$", i), (t, 3)--(t, 2), Arrow); + +void transfer(real s1, real s2, real r1, real ts) { + draw((s1,6.8)--(s2,6.8), marker(scale(2)*dotframe)); + draw((r1,6.8){down}..{down}(s2,5.5), Arrow); + draw((s2,5.5){down}..{down}(s2-ts,4.5), blue, Arrow); + draw((s2-ts,4.5){down}..{down}(r1,3.2), Arrow); + draw((r1,3.1), marker(scale(2)*dotframe)); +} + +// First transfer +transfer(1, 3, 2.5, 1.5); + +// Second transfer +transfer(7, 9, 7.5, 1.5); --- music-1.0.7.orig/doc/figures/ticklogic2.asy +++ music-1.0.7/doc/figures/ticklogic2.asy @@ -0,0 +1,38 @@ +import markers; + +unitsize(10mm); + +label("Sender", (5, 8.5)); +label("MUSIC", (0, 3), NE); +label("MPI", (0, 4.5), NE); +label("Receiver", (5, 1.5)); + +draw(box((10,8), (0,9)), dashed); +filldraw(box((10,3), (0,7)), gray(0.8), dotted); +draw(box((10,1), (0,2)), dashed); +filldraw(box((10,5.5), (0,4.5)), gray(0.5)); + +draw("Simulated Time", (0,0)--(10,0), Arrow); + +// Senders ticks +int i=1; +for (real t=2.5; t<10; t+=5, ++i) + draw(format("$s_{%d}$", i), (t, 8)--(t, 7), Arrow); + +// Receivers ticks +int i=1; +for (real t=1; t<10; t+=2, ++i) + draw(format("$r_{%d}$", i), (t, 3)--(t, 2), Arrow); + +void transfer(real s1, real s2, real r1, real ts) { + draw((s1,6.8)--(s2,6.8), marker(scale(2)*dotframe)); + draw((r1,6.8){down}..{down}(s2,5.5), Arrow); + draw((s2,5.5){down}..{down}(s2-ts,4.5), blue, Arrow); + draw((s2-ts,4.5){down}..{down}(r1,3.2), Arrow); + draw((r1,3.1), marker(scale(2)*dotframe)); +} + +// Transfers +transfer(2.5, 7.5, 3, 4.5); +transfer(2.5, 7.5, 5, 4.5); +transfer(2.5, 7.5, 7, 4.5); --- music-1.0.7.orig/doc/figures/timeline.asy +++ music-1.0.7/doc/figures/timeline.asy @@ -0,0 +1,41 @@ +import markers; + +unitsize(10mm); + +real Apos = 6; +real Bpos = 2; + +real Alag = 1.5; +real Blag = 0.0; + +real Aticks[] ={3, 5, 7, 9, 11, 13}; +real Bticks[] ={3, 7, 11}; + +label(scale(2)*"A", (0, Apos), W); +label(scale(2)*"B", (0, Bpos), W); + +// Application A ticks +for (int i=0; i| \emph{application\_label.port\_name} +\end{quote} +\noindent The direction of the arrow (\lstinline|->|, \lstinline|<-|) indicates the +direction of data transport. An output port can be connected to +multiple input ports while an input port can be connected to, at most, +one output port. + +Optionally, the width of the connections between applications can be +specified: +\begin{quote} + \emph{application\_label.port\_name} \lstinline|->| + \emph{application\_label.port\_name} [\emph{width}] +\end{quote} +The application label can be omitted if it refers to the application +being specified by the surrounding block. +An example of a simple configuration file can be seen in +section~\ref{sec:conffile}. Appendix~\ref{sec:specsyntax} specifies +the formal syntax of configuration files. + +\begin{rationale} + Information from the configuration file needs to be available both + in order to launch the application binaries and during the setup + phase. Since launching must be done prior to MPI initialization, it + is not possible to distribute configuration information via MPI + itself. In the reference implementation of MUSIC, environment + variables are used to distribute this information to the + applications. + + This information transfer is hidden within MUSIC, so a different + implementation of MUSIC may use another technique. In particular, + if the applications are launched from a scripting program, such as + PyNN\index{PyNN}, that program must also take care of transferring + the relevant configuration information to the applications. +\end{rationale} + + +\chapter{Application Program Interface} + +\section{Conventions} + +This chapter describes the API to the MUSIC library. The API is +object oriented and all communication with the library is performed +via instance methods of different classes of objects. Appendix +\ref{app:cint} presents an alternative C interface. The most common +way of passing objects as arguments in MUSIC is via pointers. The +only exception is the Setup constructor. The convention regarding +memory management is that the caller should make sure that objects +exist in memory during the entire execution of the method, and is also +responsible for the deallocation of objects afterwards. + + +\section{Error handling} + +MUSIC attempts to fall back on the error handling mechanisms of MPI. +A MUSIC exception thus results in a call to the MPI error handler. +A particular implementation of the MUSIC library does not guarantee +that it handles all kinds of errors that may occur during MUSIC calls. +Each error handled by MUSIC generates an exception, and MUSIC installs +suitable error codes, classes and strings so that the MPI error +handler is able to generate suitable error messages. + +MUSIC follows the style of error handling in the MPI standard, which +is described in sections 7.2 and 7.3 in the MPI 1.1 +report\cite{mpi1.1} and in section 2.8 of the MPI 2.0 +report\cite{mpi2.0}. The default error handler of MPI is +\lstinline|MPI_ERRORS_ARE_FATAL| which means that any error handled by +MUSIC will result in the program being aborted. Using the error +handling of MPI requires features only described in the MPI 2.0 +report. For MPI implementations which lack this support, MUSIC uses +its own error handler which has the same behavior as +\lstinline|MPI_ERRORS_ARE_FATAL|. + +\begin{rationale} + MUSIC adheres to the error handling strategy of MPI since the + application is already using MPI and should not need to implement a + second error handling strategy when converted to use MUSIC. +\end{rationale} + +\section{Setup} + +\subsection{The setup constructor} + +Each application initializes the MUSIC library through a call to the +Setup constructor\index{setup}. This constructor, in turn, calls +\lstinline|MPI::Init|\index{MPI::Init}\index{init} to initialize +MPI\index{initialize MPI}. The Setup constructor creates the Setup +object through which the application can retrieve configuration +information, get an application wide communicator, and setup ports. + +\begin{head}{Setup} + Setup::Setup (int& argc, char**& argv) +\end{head} +\begin{parameters} + \lstinline|argc| &% + reference to the \lstinline|argc| argument of \lstinline|main| \\ + \lstinline|argv| &% + reference to the \lstinline|argv| argument of \lstinline|main| \\ +\end{parameters} + +This constructor must be called at most once; subsequent calls are +erroneous. It accepts the \lstinline|argc| and \lstinline|argv| that are +provided by the arguments to \lstinline|main|. +\index{argc}\index{argv} + +\begin{code}{Initializing MUSIC} +int main (int argc, char *argv[]) +{ + MUSIC::Setup* setup = new MUSIC::Setup (argc, argv); + + /* parse arguments */ + /* rest of program */ +} +\end{code} + +\begin{rationale} + The idea behind creating a specific setup object is to ensure that + the application does not accidentally call functions relevant only + for the setup phase at other times. +\end{rationale} + + +\subsection{Communicators} + +During a multi-simulation the MUSIC library will create a unique +intra-communi\-cator over the group of processes assigned to each +application. This application wide communicator takes the role of the +global communicator \lstinline|MPI::COMM_WORLD| and is retrieved from +the setup object through a call to the \lstinline|communicator| +method.\index{communicator} + +\begin{head}{communicator} + MPI::Intracomm Setup::communicator () +\end{head} +\begin{parameters} + \emph{return value} & the application wide communicator \\ +\end{parameters} + +The application is supposed to use the application wide communicator +in place of +\lstinline|MPI::COMM_WORLD|\index{MPI::COMM\_WORLD}\index{COMM\_WORLD}. If +the application binary has been launched using \lstinline|mpirun| +instead of the \lstinline|music| utility, \lstinline|communicator ()| +will return \lstinline|MPI::COMM_WORLD| as the application wide +communicator. + +\pagebreak +\index{rank}\index{Get\_rank} +\begin{code}{Accessing the application-wide communicator} +/* communicator with global scope */ +extern MPI_Comm comm; + +... +{ + ... + comm = setup->communicator (); + int rank = comm.Get_rank (); + ... +} +\end{code} + +\begin{rationale} + An alternative to provide the \lstinline|communicator| function + would have been to redefine \lstinline|MPI::COMM_WORLD|. This would + ensure that an application does not accidentally use the global + communicator. However, it may not always be possible to dynamically + redefine this variable in all MPI implementations, so for the sake + of portability, we have chosen a more straightforward technique. +\end{rationale} + + +\subsection{Port creation} + +Ports\index{ports} are named sources (output ports) or sinks (input +ports) of data flows. Output and input ports are distinct classes. +Ports are further subdivided into distinct classes depending on +whether they handle continuous data, event data or messages. + +\index{publish output}\index{publish input} +\begin{head}{publishContOutput,publishContInput, + ,publishEventOutput,publishEventInput, + ,publishMessageOutput,publishMessageInput} + ContOutputPort* + Setup::publishContOutput (string id) + + ContInputPort* + Setup::publishContInput (string id) + + EventOutputPort* + Setup::publishEventOutput (string id) + + EventInputPort* + Setup::publishEventInput (string id) + + MessageOutputPort* + Setup::publishMessageOutput (string id) + + MessageInputPort* + Setup::publishMessageInput (string id) +\end{head} +\begin{parameters} + \lstinline|id| & port name \\ + \emph{return value} & an unmapped port \\ +\end{parameters} + +Ports have two stages in life: the \emph{unmapped} stage and the +\emph{mapped} stage. A port is unmapped when created. The MUSIC +configuration file specifies connections between ports. It is +possible to ask an unmapped port if it is connected, if it has a width +specified and, if so, what width it has. A port becomes mapped when +its method \lstinline|map| is called. + +\begin{code}{Creating an unmapped port} +ContOutputPort* out = + setup->publishContOutput ("out"); +\end{code} + +\subsection{General port methods} + +The port API includes methods to ask a port if it is connected, if it +has a width specified, and, if so, what that width is. + +\subsubsection{Port connectivity} + +The method \lstinline|isConnected| is used to check if the user has +specified a connection of this port to another port in the +configuration file. + +\index{isConnected}\index{connected port} +\begin{head}{isConnected} + bool Port::isConnected () +\end{head} +\begin{parameters} + \emph{return value} & \lstinline|true| only if connected\\ +\end{parameters} + +This method is typically used in cases where the use of some of the +ports of the application is optional. In such a case, it is not +sensible to allocate any application resources to support the data +flow in question. One example is if one wants to support output of +membrane potentials from a certain population of cells, but don't want +to waste resources if no one is listening. + +\begin{code}{Optional handling of ports} +ContOutputPort* out = + setup->publishContOutput ("Vm"); +/* map port only if anyone is listening */ +if (out->isConnected ()) + /* allocate application resources and map port */ +\end{code} + +\subsubsection{Port width} +\label{sec:width} + +The width of a port\index{port width}, that is the number of data +elements transferred in parallel from a cont port or the largest +possible id of an event port $+$ 1, can be specified in the +configuration file. This should be thought of as a request for a +given width. Applications can use the method \lstinline|hasWidth| to +determine if a width has been specified and retrieve it using +\lstinline|width|. Message ports do not have width. + +\index{hasWidth} +\begin{head}{hasWidth} + bool Port::hasWidth () +\end{head} +\begin{parameters} + \emph{return value} & \lstinline|true| only if port width has been + specified \\ +\end{parameters} + +\index{width} +\begin{head}{width} + int Port::width () +\end{head} +\begin{parameters} + \emph{return value} & port width \\ +\end{parameters} + +\begin{rationale} + Applications can use the above methods to adapt their port width. A + typical usage would be a general purpose post-processing tool which + receives information from an ongoing simulation. Such a tool can + publish a number of optional input ports and then use + \lstinline|isConnected| and \lstinline|width| to adapt its internal + processing depending on what kind of data source it is actually + connected to. See example \ref{code:adaptivewidth}. +\end{rationale} + + +\begin{code}{Publishing port of adaptive width\label{code:adaptivewidth}} +{ + ... + /* Publishing a port of adaptive width */ + double* stateVars; + MUSIC::ContInputPort* in = + setup->publishContInput ("in"); + if (!in->hasWidth ()) + /* report error */ + else + { + int size = in->width (); + /* for clarity we assume that nElements + is a multiple of size */ + int nLocal = nElements / size; + /* example continues as in next example */ + ... + + } +} +\end{code} + + +\subsection{Mapping cont ports} +\index{cont ports} + +A port is informed about what data exists locally and how to access it +by mapping it. Cont ports transfer data from or to memory during +\lstinline|tick| calls and need to know the layout of data in memory. +In addition, the marshalling (conversion between different bit level +representations) performed on heterogeneous clusters requires +information about the data type being transferred. This information +is captured by the data map argument \lstinline|dMap|. The +\lstinline|DataMap| type is described in section \ref{sec:datamap} +below. + +\clearpage +\index{map}\index{mapping cont ports} +\begin{head}{map} + void ContOutputPort::map (DataMap* dMap, + int maxBuffered) + + void ContInputPort::map (DataMap* dMap, + double delay, + int maxBuffered, + bool interpolate) +\end{head} +\begin{parameters} + \lstinline|dMap| & the data map associated with the port \\ + \lstinline|delay| & delay of data arrival in simulation time (s) \\ + \lstinline|maxBuffered| & maximal amount of data buffered (ticks) + \\ + \lstinline|interpolate| & enable interpolation (boolean) \\ +\end{parameters} + +The optional argument \lstinline|delay| informs MUSIC of when, +according to simulation time, to sample data on the sender side. If +enabled, linear interpolation is used to obtain an approximation of +the state at this time. The default delay is zero. Delayed continuous +data may be used in connectionist networks when modeling brain +pathways. A delay is \emph{required} at some point when communicating +continuous data in a loop (c.f. section \ref{sec:timing}). + +Buffering data in output and input ports gives more efficient +communication since data can be sent fewer times in larger packets. +By default MUSIC buffers some reasonable amount of data. In certain +situations it is necessary to be careful about memory usage. Using +the optional argument \lstinline|maxBuffered| the application can +give MUSIC a bound on how much data to buffer. MUSIC decides how much +data to buffer based on the lowest \lstinline|maxBuffered| parameter +given when mapping each of a set of connected ports and on latency +considerations when applications are connected in loops. A +\lstinline|maxBuffered| value of \(N\) ticks means: don't buffer more +data than is sufficient for communicating at every \(N\)\,th tick. + +When the optional argument \lstinline|interpolate| is +\lstinline|true|, MUSIC uses linear interpolation to determine the +values delivered on the receiver side. This is the default behavior. +By passing \lstinline|false| this interpolation can be switched off in +which case MUSIC selects the sample on the sender side which is +closest according to simulation time. + +\clearpage +\begin{code}{Mapping ports to internal data\label{code:mapping}} +{ + ... + int size = comm.Get_size (); + int rank = comm.Get_rank (); + /* for clarity we assume that nElements + is a multiple of size */ + int nLocal = nElements / size; + double* stateVars = new double[nLocal]; + MUSIC::ContInputPort* out = + setup->publishContOutput ("out"); + MUSIC::ArrayData dMap (stateVars, MPI::DOUBLE, + rank * nLocal, nLocal); + out->map (&dMap); + ... +} +\end{code} + + +\subsection{Mapping event ports} +\index{event ports} + +\index{map}\index{mapping event ports} +\begin{head}{map} + void EventOutputPort::map (IndexMap* indices, + Index::Type type, + int maxBuffered) + + void EventInputPort::map (IndexMap* indices, + EventHandler* handleEvent, + double accLatency, + int maxBuffered) +\end{head} +\begin{parameters} + \lstinline|indices| & the index map associated with the port \\ + \lstinline|type| & the indexing type used (local or global) \\ + \lstinline|handleEvent| & a user-defined event handler \\ + \lstinline|accLatency| & acceptable latency for incoming data (s) \\ + \lstinline|maxBuffered| & maximal amount of data buffered (ticks) \\ +\end{parameters} + +Since event ports don't access data the same way as cont ports, they +do not require a full \lstinline|DataMap|. Instead, an +\lstinline|IndexMap| is used to describe how indices in the +application should be mapped to the shared global indices common for +sender and receiver. The applications has the choice of using local +indices or bypassing the index transformation by directly using the +shared global indices when labelling events. This is controlled by +the \lstinline|type| parameter which can be set to +\lstinline|MUSIC::Index::LOCAL| or \lstinline|MUSIC::Index::GLOBAL|. + +Events are communicated to the application through an \emph{event + handler}\index{event handler}. The event handler is called by MUSIC +when the application calls \lstinline|tick|. It is called once for +every event delivered. + +Some spiking neural network models include axonal delays. The MUSIC +framework assumes that handling and delivery of delayed spikes occurs +on the receiver side. In such a case, the receiver may allow MUSIC to +deliver a spike event later than its time stamp according to local +time. The maximal acceptable latency is specified through the +\lstinline|accLatency|\index{accLatency} argument. + +The optional argument \lstinline|maxBuffered|\index{maxBuffered} +has a similar meaning as for cont ports above but the actual amount +of data buffered is, in this case, not deterministic since it is +dependent on spike rate. + + +\subsubsection{Sending events} +\index{sending events} + +The sender registers events for transmission by calling the method +\lstinline|insertEvent|. + +\index{insertEvent} +\begin{head}{insertEvent} + void EventOutputPort::insertEvent (double t, + LocalIndex id) + void EventOutputPort::insertEvent (double t, + GlobalIndex id) +\end{head} +\begin{parameters} + \lstinline|t| & trigger time of the event (s) \\ + \lstinline|id| & the local or global index of the event \\ +\end{parameters} + +MUSIC guarantees that this event will be delivered through a call to +the user-specified \lstinline|EventHandler| on the receiver side no +later that the acceptable latency relative to receiver local time. +The time \lstinline|t| must be between the simulation time of the last +tick and that of the next. + +The parameter \lstinline|id| should be converted from \lstinline|int| +to \lstinline|LocalIndex| or \lstinline|GlobalIndex| to indicate what +kind of indices are used in the application. + + +\subsubsection{Receiving events} +\index{receiving events} + +\index{EventHandler} +\begin{head}{EventHandlerLocalIndex,EventHandlerGlobalIndex,operator} + class EventHandlerLocalIndex { + public: + virtual void operator () (double t, + LocalIndex id) = 0; + }; + + class EventHandlerLocalIndex { + public: + virtual void operator () (double t, + GlobalIndex id) = 0; + }; +\end{head} +\begin{parameters} + \lstinline|t| & trigger time of the event (s) \\ + \lstinline|id| & local or global index if the event \\ +\end{parameters} + +Event handlers are called by event input ports to deliver events. The +application is supposed to customize either +\lstinline|LocalEventHandler| or \lstinline|GlobalEventHandler| by +subclassing one of them (depending on the indexing +scheme the application uses). + + +\clearpage +\subsection{Mapping message ports} +\index{message ports} + +Message ports behave similarly to event ports in that messages are +sent and delivered using similar mechanisms, but while events are +routed between processes based on event indices, messages are routed to all +processes on the receiver side which have provided a +\lstinline|MessageHandler| to \lstinline|map|. All arguments to +\lstinline|map| for message ports are optional. + +\index{map}\index{mapping message ports} +\begin{head}{map} + void MessageOutputPort::map (int maxBuffered) + + void MessageInputPort::map (MessageHandler* handler, + double accLatency, + int maxBuffered) +\end{head} +\begin{parameters} + \lstinline|handler| & a user-defined message handler \\ + \lstinline|accLatency| & acceptable latency for incoming data (s) \\ + \lstinline|maxBuffered| & maximal amount of data buffered (ticks) \\ +\end{parameters} + + +\subsubsection{Sending messages} +\index{sending messages} + +The sender registers a message for transmission by calling the method\\ +\lstinline|insertMessage|. + +\index{insertMessage} +\begin{head}{insertMessage} + void MessageOutputPort::insertMessage (double t, + void* msg, + size_t size) +\end{head} +\begin{parameters} + \lstinline|t| & time stamp (s) \\ + \lstinline|msg| & pointer to message \\ + \lstinline|size| & size of message in bytes \\ +\end{parameters} + +MUSIC will deliver this message through a call to the user-specified \\ +\lstinline|MessageHandler| on the receiver side no later than +\lstinline|accLatency| with regard to the time stamp. + +\begin{code}{Sending a message} +{ + ... + char m[] = "string to send"; + port->insertMessage (runtime->time (), m, sizeof (m)); + ... +} +\end{code} + +\pagebreak +\subsubsection{Receiving messages} +\index{receiving messages} + +\begin{head}{MessageHandler,operator} + class MessageHandler { + public: + virtual void operator () (double t, + void* msg, + size_t size) = 0; + }; +\end{head} +\begin{parameters} + \lstinline|t| & time stamp supplied by sender (s) \\ + \lstinline|msg| & pointer to message subclass instance \\ + \lstinline|size| & size of message instance in bytes \\ +\end{parameters} + +Message handlers are called by message input ports to deliver +messages. The application is supposed to customize +\lstinline|MessageHandler| by subclassing. It is recommended that +messages are text strings with the syntax of the interpreter language +of the receiving application, and that these text strings originate +from a user-specified configuration file read by the sending +application. + +The message given to the \lstinline|MessageHandler| is deallocated by +the MUSIC library. + + +\subsection{Index maps} +\index{index maps} + +An \lstinline|IndexMap| is a mapping from the local data element +indices to shared global indices. An index map instance thus holds +information of which subset of the shared global indices belong to the +local MPI process and of their local order. MUSIC implements two +subclasses of \lstinline|IndexMap|: \lstinline|PermutationIndex| and +\lstinline|LinearIndex|. The most general form is +\lstinline|PermutationIndex| which allows for an arbitrary mapping. + +\index{PermutationIndex} +\begin{head}{PermutationIndex} + PermutationIndex::PermutationIndex (int* indices, + int size) +\end{head} +\begin{parameters} + \lstinline|indices| & vector of shared indices \\ + \lstinline|size| & number of shared indices \\ +\end{parameters} + +\index{LinearIndex} +\begin{head}{LinearIndex} + LinearIndex::LinearIndex (int baseIndex, int size) +\end{head} +\begin{parameters} + \lstinline|baseIndex| & shared index corresponding to local index zero \\ + \lstinline|size| & number of contiguous indices in this process \\ +\end{parameters} + +When a cont output port is mapped it becomes associated with a set of +state variables (or other data) in the memory of the sender. When the +receiver calls \lstinline|runtime::tick|, an estimate of the values +of these variables are stored in a set of variables associated with an +input port on the receiver side. Similarly, an event output port is +mapped to a set of event id:s. + +While the number of variables or id:s on the receiver side is always +the same as on the sender side, the data can be distributed in +different ways between MPI processes on the sender side compared to +the receiver side. In fact, sender and receiver may consist of +different numbers of processes. + +Index maps are used in each MPI process to tell MUSIC how data is +distributed and ordered by enumerating the shared indices +represented by the process in local order. + +\subsection{Data maps} +\label{sec:datamap} +\index{data maps} + +A \lstinline|DataMap| encapsulates how a port accesses its data. +While an index map is a mapping between two kinds of indices, the data +map also contains information about where in memory data resides, how +it is structured, and, the type of the data elements. +\lstinline|ArrayData| is a subclass of \lstinline|DataMap| which +describes arrays of data elements. See example \ref{code:mapping}. + +\index{ArrayData} +\begin{head}{ArrayData} + ArrayData::ArrayData (void* buffer, MPI_Datatype type, + IndexMap* map) +\end{head} +\begin{parameters} + \lstinline|buffer| & data memory location \\ + \lstinline|type| & data type \\ + \lstinline|map| & index map \\ +\end{parameters} + +Since data organized in arrays is common, MUSIC provides a convenience +form of the array data map constructor which also creates a linear +index map: + +\begin{head}{ArrayData} + ArrayData::ArrayData (void* buffer, + MPI_Datatype type, + int baseIndex, + int size) +\end{head} +\begin{parameters} + \lstinline|buffer| & data memory location \\ + \lstinline|type| & data type \\ + \lstinline|baseIndex| & shared index of first local element \\ + \lstinline|size| & number of contiguous indices in this process \\ +\end{parameters} + + +\subsection{Configuration variables} +\index{configuration variables} + +The values of all variables defined in the configuration file can be +queried using the method \lstinline|config|. + +\index{config} +\begin{head}{config} + bool Setup::config (string name, string* result) + + bool Setup::config (string name, int* result) + + bool Setup::config (string name, double* result) +\end{head} +\begin{parameters} + \lstinline|name| & variable name \\ + \lstinline|result| & pointer to location where result should go \\ + \emph{return value} & true if value of correct type was found \\ +\end{parameters} + +Querying for a value of type \lstinline|int| or \lstinline|double| +expects a value of the correct type, if defined in the configuration +file. If the variable is defined, but its value can't be translated +into the correct type this causes an error condition. + +\begin{code}{Querying configuration variables} +/* Retrieving the parameter gKCa + from configuration file */ +double gKCa; +if (!config ("gKCa", &gKCa)) + gKCa = 29.5e-9; // default value +\end{code} + +\section{Runtime} + +\subsection{The runtime constructor} + +\begin{head}{runtime} + Runtime::Runtime (Setup* s, double h) +\end{head} +\begin{parameters} + \lstinline|s| & pointer to the Setup object \\ + \lstinline|h| & simulated time increment at each tick (s) \\ +\end{parameters} + +Creation of the runtime object marks the transition from the setup to +the runtime phase. The runtime object constructor destroys the Setup +object, effectively making it impossible to create new ports. All +data structures which have been associated with ports during mapping +must be initialized to some suitable start value at the time of the +call to the runtime constructor. These values are used during early +data transfers of data sampled at negative values of simulation time +and, thus, not available. + +\begin{code}{Runtime} +... +MUSIC::Runtime runtime = MUSIC::Runtime (setup, stepSize); +... +\end{code} + +\begin{rationale} + The step size is given as a real number (in seconds) since this + makes most sense from the applications point of view. Internally, + this number is converted to an integer (using the time micro step + time base). This is made to ensure that all processes use exactly + the same numbers even when the multi-simulation is running on mixed + architectures. Both sides of a connection must agree on when data + is transferred over the MPI connector to minimize the + need for handshaking during the runtime phase. +\end{rationale} + +\begin{rationale} + In order to create a deterministic schedule for buffering and data + transfer, we require that \lstinline|tick| increments simulated time + by a fixed amount each time. We realize that some applications may + use a variable time step\index{variable time step} for their + numerical integrations, which may then make it harder to execute + these tick calls at the right time. However, allowing variable tick + steps would have made it impossible to use a pre-computed + deterministic schedule and enforced repeated handshaking throughout + the runtime phase, resulting in a substantial performance + degradation. + + Note that the tick step does not need to be equal to the internally + used integration step\index{integration step}. We believe that most + large scale parallel simulators already have some means for fixed + interval operations, e.g. to handle logging to files or graphics, + which may be utilized also for the tick calls. +\end{rationale} + + +\subsection{The tick} +\index{tick} + +\begin{head}{tick} + void Runtime::tick () +\end{head} +\begin{parameters} +\end{parameters} + +The tick function must be called at regular intervals in simulation +time. The application chooses the interval as a parameter to the +\lstinline|Runtime| constructor, normally based on the time step used +in the application. The \lstinline|tick| function is typically called +in the main simulation loop of each application. Different +applications may use different tick intervals and MUSIC will ensure +that time is incremented consistently throughout the multi-simulation. + +Before \lstinline|tick| is called, the application must ensure that +all data mapped for output is valid. At the \lstinline|tick| call, +time is incremented and data mapped for input is updated to reflect +the new time. Further, installed event handlers will be called +\emph{during} the \lstinline|tick| call to deliver events. + +The MUSIC library may, or may not, exchange data with other +applications at the tick call. The application must ensure that +exported data values are valid when \lstinline|tick| is called. It +must also expect that imported values may change and that event and +message handlers are called. + +\begin{rationale} + The idea behind the \lstinline|tick| call is to hide the complexity + of data buffering and MPI transfer from the application. For + efficient data transfer, MUSIC will try to buffer data both at the + sending and receiving port in order to send data in large chunks. + Internally, MUSIC will use a pre-computed schedule to keep track of + at what ticks the actual data transfer should take place and when + data should instead be buffered for later transfer. +\end{rationale} + + +\subsection{Simulation time} +\index{simulation time} + +The method \lstinline|time| returns local time in seconds. + +\index{time} +\begin{head}{time} + double Runtime::time () +\end{head} +\begin{parameters} + \emph{return value} & local time (s) \\ +\end{parameters} + +\lstinline|time| returns the local time. Time starts at 0\,s and is +incremented at every \lstinline|tick| call. While it is possible, and +recommended, to let MUSIC keep track of time for the application, this +is not required. + +\begin{rationale} + To schedule data transfers, MUSIC needs to keep track of the + simulation time of all applications via its internal integer + representation. If the application independently manages its own + clock, typically by incrementing a floating point variable, there is + a risk for drift between the two time representations. The + \lstinline|time| function makes it possible for the application to + keep its clock in perfect synchronization with time in the other + applications. +\end{rationale} + + +\subsection{Finalization} + +An application supporting MUSIC should replace its call to +\lstinline|MPI::Finalize| with a call to \lstinline|MUSIC::finalize|. + +\index{finalize} +\begin{head}{finalize} + void Runtime::finalize () +\end{head} +\begin{parameters} +\end{parameters} + +\lstinline|MUSIC::finalize| makes sure all internally buffered data is +sent and finally calls \lstinline|MPI::Finalize|. Note that this +means that communication via MPI will not be possible afterwards. + + +\chapter{Adapting Existing Applications} + +In this chapter we will highlight the steps necessary to adapt an +existing neural simulator to MUSIC. We will assume that the simulator +is already using MPI to simulate large networks of interconnected +neurons. + +The two main tasks that need to be handled are: firstly, to create and +map ports for data to be imported and exported, and, secondly, to +ensure that the \lstinline|tick| function is called at regular +intervals. + + +\section{Creating and Mapping Ports} + +The application needs to inform MUSIC about what data to import and +export, and where this data resides. A simulator will typically use +some sort of script files where the user specifies the model and other +aspects of the simulation. If possible, it is desirable to extend the +scripting language of the simulator so that the user can specify what +model variables to communicate, and what names to use for ports. + +Assuming that we have introduced such constructs into the scripting +language, we must decide on a suitable point in the initialization +process where ports should be created and mapped. Since continuous +data is read from, or written to, application memory space, the +program must have allocated its runtime data structures in order to +perform the mapping. + +Communication of spikes will use event ports. Function calls are used +to send and receive individual spike events. Sending of spikes is +relatively straightforward, since the only thing needed is to add a +call to the method \lstinline|insertEvent| at the location where +spikes are normally detected in the program. Receiving spikes +requires more administration, since the spikes can be received earlier +than when they should reach their destination compartment. It is +therefore necessary to save incoming spikes in some sort of sorted +buffer (typically a priority queue). + +\begin{figure} + \begin{center} + \begin{minipage}[t]{0.45\textwidth} + \includegraphics[width=\textwidth]{figures/remapping} + \caption[Processing of incoming data]{\label{fig:remapping1} + The sender application presents the data to the output port in + the same order as it is stored internally. The receiving + application will see the transferred data in the same order + and will explicitly have to implement a proper reordering to + implement a typical synaptic projection. + } + \end{minipage} + \hfill + \begin{minipage}[t]{0.45\textwidth} + \includegraphics[width=\textwidth]{figures/remapping2} + \caption[Remapping of data within MUSIC]{\label{fig:remapping2} + If there is a one-to-one correspondence between sending and + receiving neurons, the receiving application can specify an + appropriate index map to instruct MUSIC to send the data + directly to the right destination. + } + \end{minipage} + \end{center} +\end{figure} + +In addition, MUSIC will always present the spikes as they appear in +the sending group of neurons. In most situations, the receiving +application will want to implement a remapping to the target +compartments, as illustrated in figure~\ref{fig:remapping1}. One spike +may thus end up at multiple postsynaptic compartments, spread out over +the processors of the receiving application. + +In some situations it may be desirable for the receiving application +to avoid this remapping. The application can then utilize the different +forms of mappings available in MUSIC to create a general permutation +so that MUSIC will send spikes directly to the processor where they +should be handled. This situation is illustrated in +figure~\ref{fig:remapping2} + + +\section{Advancing Simulation Time} + +The application must call the \lstinline|tick| function repeatedly +throughout the simulation. The application will have to ensure that +these calls are made at regular intervals, as specified to the runtime +constructor. Note that this refers to \emph{simulated time}; there is +no need to consider how much computation time (``wall clock time'') is +used between tick calls. + +If the application makes use of variable time steps internally, it may +be necessary to use some sort of checkpoints at fixed intervals where +tick can be called. It is not necessary to call tick at every +integration time step, but the calls should not be too infrequent. + +The tick calls are the only times during runtime when MUSIC will use +MPI. MUSIC will then use its own communicators, not to interfere with +the MPI operations of the application. Still, we recommend that the +application does not intersperse the tick calls with ongoing MPI +operations. + +When sending continuous values the application must ensure that data +arrays mapped for output are filled with values relevant for the time +of the \emph{next} tick. After the \lstinline|tick| call, data arrays +mapped for input will be filled with imported data belonging to the +same point in time. Note that \lstinline|Runtime::time| is updated +\emph{during} the \lstinline|tick| call to reflect the current +simulation time. + + +\section{Initialization and Finalization} + +\subsection{Initiate MUSIC}\index{initiate MUSIC} + +The idea here is to replace the call to \lstinline|MPI::Init| with a +call to the \lstinline|MUSIC:Setup| constructor. The Setup +constructor calls \lstinline|MPI::Init| for the application. + +The application will have to replace all uses of the global +communicator \lstinline|MPI::COMM_WORLD| with the communicator +supplied by MUSIC. The global communicator will be global over all +applications and it is necessary to limit the MPI operations to the +group of MPI processes belonging to the application. + +There should be no need to link an application differently when it is +used together with other applications in a MUSIC setting compared to +when it is used in a stand-alone setting. In order to support +``standard'' operation for the application, +\lstinline|Setup::communicator ()|, therefore, will return +\lstinline|MPI::COMM_WORLD| if the job is started directly with +\lstinline|mpirun| instead of with the MUSIC launcher. + + + +\subsection{Initiate the runtime phase} + +Creating the runtime object will implicitly call the \lstinline|Setup| +object destructor to ensure that the application will no longer be +able to change the communication pattern. At this stage, MUSIC can +build the plan for communication between different processes. + +\subsection{Finalize MUSIC}\index{finalize}\index{terminate} + +The application should also replace its call to +\lstinline|MPI::Finalize|, normally used to shut down communication, +by a call to \lstinline|MUSIC::finalize|. This will internally call +\lstinline|MPI::Finalize| after having flushed all pending data from +internal buffers. + +\bibliographystyle{unsrtnat} +\bibliography{music-rfc} + +\appendix + +\chapter{A Complete Example} + +This chapter shows a minimal but still complete example. It consists +of two applications, \texttt{waveproducer} and \texttt{waveconsumer}, +and a configuration file used to launch and connect them. + + +\section{Configuration File} +\label{sec:conffile} + +The configuration file starts the waveproducer application on four +processors and waveconsumer on three. + +\lstinputlisting[language=Clean,frame=single]{../test/wavetest.music} + + +\section{Data Generating Application} + +\lstinputlisting{../test/waveproducer.cc} + + +\section{Data Consuming Application} + +\lstinputlisting{../test/waveconsumer.cc} + + +\chapter{C Interface} +\label{app:cint} + +Most elements of the C interface can be constructed from their C++ +counterparts using a few translation rules: + +\begin{enumerate} +\item All identifiers have the prefix \lstinline|MUSIC_|. +\item Constructors translate to \lstinline|create| followed by the + class name. +\item Destructors translate to \lstinline|destroy| followed by the + class name. +\item Methods translate to class name followed by method name. +\item References translate to pointers. +\item Strings translate to \lstinline|char *|. +\item Optional C++ arguments are required in C. +\end{enumerate} + +Entries which do not strictly follow these rules are preceded with an +extra comment in the following listing. + +\lstinputlisting{music-c-int.h} + +\chapter{Specification File Syntax} +\label{sec:specsyntax} + +\newcommand{\nt}[1]{$<$#1$>$} + +\begin{tabular}{lcl} +\nt{simulation spec} & ::= & \{ \nt{application block} \} \\ +\nt{application block} & ::= & \nt{newline} '[' \nt{application id} ']' \{ \nt{declaration} +\} \\ +\nt{application id} & ::= & \nt{symbol} \\ +\nt{declaration} & ::= & \nt{variable def} $|$ \nt{connection} \\ +\nt{variable def} & ::= & \nt{variable} '=' \nt{value} \\ +\nt{variable} & ::= & \nt{symbol} \\ +\nt{value} & ::= & \nt{integer} $|$ \nt{float} $|$ \nt{string} \\ +\nt{connection} & ::= & \nt{port id} \nt{direction} \nt{port id} [ \nt{width} ] \\ +\nt{port id} & ::= & \nt{application id} '.' \nt{port} $|$ +\nt{port} \\ +\nt{port} & ::= & \nt{symbol} \\ +\nt{direction} & ::= & $->$ $|$ $<-$ \\ +\nt{width} & ::= & '[' \nt{integer} ']' \\ +\end{tabular} + +\printindex + +\end{document} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% eval: (flyspell-mode 1) +%%% eval: (ispell-change-dictionary "american") +%%% eval: (flyspell-buffer) +%%% End: --- music-1.0.7.orig/doc/music-rfc.bib +++ music-1.0.7/doc/music-rfc.bib @@ -0,0 +1,15 @@ +@Misc{mpi1.1, + author = {Message Passing Interface Forum}, + title = {{MPI}: A Message-Passing Interface Standard}, + month = {November}, + year = 2003, + howpublished = {{\url{http://www.mpi-forum.org/docs/mpi-11-html/mpi-report.html}}} +} + +@Misc{mpi2.0, + author = {Message Passing Interface Forum}, + title = {{MPI}-2: Extensions to the Message-Passing Interface}, + month = {November}, + year = 2003, + howpublished = {{\url{http://www.mpi-forum.org/docs/mpi-20-html/mpi2\-report.html}}} +} --- music-1.0.7.orig/utils/VisualiseNeurons.cpp +++ music-1.0.7/utils/VisualiseNeurons.cpp @@ -18,7 +18,7 @@ // VisualiseNeurons.cpp written by Johannes Hjorth, hjorth@nada.kth.se - +#include #include "VisualiseNeurons.h" void VisualiseNeurons::printHelp() {