diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/mpi/test/python | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/mpi/test/python')
-rw-r--r-- | src/boost/libs/mpi/test/python/all_gather_test.py | 25 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/all_reduce_test.py | 29 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/all_to_all_test.py | 30 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/broadcast_test.py | 29 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/gather_test.py | 32 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/generators.py | 23 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/nonblocking_test.py | 131 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/reduce_test.py | 31 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/ring_test.py | 42 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/scan_test.py | 29 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/scatter_test.py | 36 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/skeleton_content_test.cpp | 37 | ||||
-rw-r--r-- | src/boost/libs/mpi/test/python/skeleton_content_test.py | 75 |
13 files changed, 549 insertions, 0 deletions
diff --git a/src/boost/libs/mpi/test/python/all_gather_test.py b/src/boost/libs/mpi/test/python/all_gather_test.py new file mode 100644 index 00000000..824dc892 --- /dev/null +++ b/src/boost/libs/mpi/test/python/all_gather_test.py @@ -0,0 +1,25 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test all_gather() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def all_gather_test(comm, generator, kind): + if comm.rank == 0: print ("Gathering %s..." % (kind,)), + my_value = generator(comm.rank) + result = mpi.all_gather(comm, my_value) + for p in range(0, comm.size): + assert result[p] == generator(p) + if comm.rank == 0: print "OK." + + return + +all_gather_test(mpi.world, int_generator, "integers") +all_gather_test(mpi.world, gps_generator, "GPS positions") +all_gather_test(mpi.world, string_generator, "strings") +all_gather_test(mpi.world, string_list_generator, "list of strings") diff --git a/src/boost/libs/mpi/test/python/all_reduce_test.py b/src/boost/libs/mpi/test/python/all_reduce_test.py new file mode 100644 index 00000000..c3285e65 --- /dev/null +++ b/src/boost/libs/mpi/test/python/all_reduce_test.py @@ -0,0 +1,29 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test all_reduce() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def all_reduce_test(comm, generator, kind, op, op_kind): + if comm.rank == 0: + print ("Reducing to %s of %s..." % (op_kind, kind)), + my_value = generator(comm.rank) + result = mpi.all_reduce(comm, my_value, op) + expected_result = generator(0); + for p in range(1, comm.size): + expected_result = op(expected_result, generator(p)) + + assert result == expected_result + if comm.rank == 0: + print "OK." + return + +all_reduce_test(mpi.world, int_generator, "integers", lambda x,y:x + y, "sum") +all_reduce_test(mpi.world, int_generator, "integers", lambda x,y:x * y, "product") +all_reduce_test(mpi.world, string_generator, "strings", lambda x,y:x + y, "concatenation") +all_reduce_test(mpi.world, string_list_generator, "list of strings", lambda x,y:x + y, "concatenation") diff --git a/src/boost/libs/mpi/test/python/all_to_all_test.py b/src/boost/libs/mpi/test/python/all_to_all_test.py new file mode 100644 index 00000000..b149bf0d --- /dev/null +++ b/src/boost/libs/mpi/test/python/all_to_all_test.py @@ -0,0 +1,30 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test all_to_all() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def all_to_all_test(comm, generator, kind): + if comm.rank == 0: + print ("All-to-all transmission of %s..." % (kind,)), + + values = list() + for p in range(0, comm.size): + values.append(generator(p)) + result = mpi.all_to_all(comm, values) + + for p in range(0, comm.size): + assert result[p] == generator(comm.rank) + + if comm.rank == 0: print "OK." + return + +all_to_all_test(mpi.world, int_generator, "integers") +all_to_all_test(mpi.world, gps_generator, "GPS positions") +all_to_all_test(mpi.world, string_generator, "strings") +all_to_all_test(mpi.world, string_list_generator, "list of strings") diff --git a/src/boost/libs/mpi/test/python/broadcast_test.py b/src/boost/libs/mpi/test/python/broadcast_test.py new file mode 100644 index 00000000..dbd53d1b --- /dev/null +++ b/src/boost/libs/mpi/test/python/broadcast_test.py @@ -0,0 +1,29 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test broadcast() collective. + +import boost.parallel.mpi as mpi + +def broadcast_test(comm, value, kind, root): + if comm.rank == root: + print ("Broadcasting %s from root %d..." % (kind, root)), + + got_value = mpi.broadcast(comm, value, root) + assert got_value == value + if comm.rank == root: + print "OK." + return + +broadcast_test(mpi.world, 17, 'integer', 0) +broadcast_test(mpi.world, 17, 'integer', 1) +broadcast_test(mpi.world, 'Hello, World!', 'string', 0) +broadcast_test(mpi.world, 'Hello, World!', 'string', 1) +broadcast_test(mpi.world, ['Hello', 'MPI', 'Python', 'World'], + 'list of strings', 0) +broadcast_test(mpi.world, ['Hello', 'MPI', 'Python', 'World'], + 'list of strings', 1) + diff --git a/src/boost/libs/mpi/test/python/gather_test.py b/src/boost/libs/mpi/test/python/gather_test.py new file mode 100644 index 00000000..d56b3a41 --- /dev/null +++ b/src/boost/libs/mpi/test/python/gather_test.py @@ -0,0 +1,32 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test gather() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def gather_test(comm, generator, kind, root): + if comm.rank == root: + print ("Gathering %s to root %d..." % (kind, root)), + my_value = generator(comm.rank) + result = mpi.gather(comm, my_value, root) + if comm.rank == root: + for p in range(0, comm.size): + assert result[p] == generator(p) + print "OK." + else: + assert result == None + return + +gather_test(mpi.world, int_generator, "integers", 0) +gather_test(mpi.world, int_generator, "integers", 1) +gather_test(mpi.world, gps_generator, "GPS positions", 0) +gather_test(mpi.world, gps_generator, "GPS positions", 1) +gather_test(mpi.world, string_generator, "strings", 0) +gather_test(mpi.world, string_generator, "strings", 1) +gather_test(mpi.world, string_list_generator, "list of strings", 0) +gather_test(mpi.world, string_list_generator, "list of strings", 1) diff --git a/src/boost/libs/mpi/test/python/generators.py b/src/boost/libs/mpi/test/python/generators.py new file mode 100644 index 00000000..8cdd3e05 --- /dev/null +++ b/src/boost/libs/mpi/test/python/generators.py @@ -0,0 +1,23 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Value generators used in the Boost.MPI Python regression tests +def int_generator(p): + return 17 + p + +def gps_generator(p): + return (39 + p, 16, 20.2799) + +def string_generator(p): + result = "%d rosebud" % p; + if p != 1: result = result + 's' + return result + +def string_list_generator(p): + result = list() + for i in range(0,p): + result.append(str(i)) + return result diff --git a/src/boost/libs/mpi/test/python/nonblocking_test.py b/src/boost/libs/mpi/test/python/nonblocking_test.py new file mode 100644 index 00000000..73b451c5 --- /dev/null +++ b/src/boost/libs/mpi/test/python/nonblocking_test.py @@ -0,0 +1,131 @@ +# (C) Copyright 2007 +# Andreas Kloeckner <inform -at- tiker.net> +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# Authors: Andreas Kloeckner + + + + +import boost.mpi as mpi +import random +import sys + +MAX_GENERATIONS = 20 +TAG_DEBUG = 0 +TAG_DATA = 1 +TAG_TERMINATE = 2 +TAG_PROGRESS_REPORT = 3 + + + + +class TagGroupListener: + """Class to help listen for only a given set of tags. + + This is contrived: Typicallly you could just listen for + mpi.any_tag and filter.""" + def __init__(self, comm, tags): + self.tags = tags + self.comm = comm + self.active_requests = {} + + def wait(self): + for tag in self.tags: + if tag not in self.active_requests: + self.active_requests[tag] = self.comm.irecv(tag=tag) + requests = mpi.RequestList(self.active_requests.values()) + data, status, index = mpi.wait_any(requests) + del self.active_requests[status.tag] + return status, data + + def cancel(self): + for r in self.active_requests.itervalues(): + r.cancel() + #r.wait() + self.active_requests = {} + + + +def rank0(): + sent_histories = (mpi.size-1)*15 + print "sending %d packets on their way" % sent_histories + send_reqs = mpi.RequestList() + for i in range(sent_histories): + dest = random.randrange(1, mpi.size) + send_reqs.append(mpi.world.isend(dest, TAG_DATA, [])) + + mpi.wait_all(send_reqs) + + completed_histories = [] + progress_reports = {} + dead_kids = [] + + tgl = TagGroupListener(mpi.world, + [TAG_DATA, TAG_DEBUG, TAG_PROGRESS_REPORT, TAG_TERMINATE]) + + def is_complete(): + for i in progress_reports.values(): + if i != sent_histories: + return False + return len(dead_kids) == mpi.size-1 + + while True: + status, data = tgl.wait() + + if status.tag == TAG_DATA: + #print "received completed history %s from %d" % (data, status.source) + completed_histories.append(data) + if len(completed_histories) == sent_histories: + print "all histories received, exiting" + for rank in range(1, mpi.size): + mpi.world.send(rank, TAG_TERMINATE, None) + elif status.tag == TAG_PROGRESS_REPORT: + progress_reports[len(data)] = progress_reports.get(len(data), 0) + 1 + elif status.tag == TAG_DEBUG: + print "[DBG %d] %s" % (status.source, data) + elif status.tag == TAG_TERMINATE: + dead_kids.append(status.source) + else: + print "unexpected tag %d from %d" % (status.tag, status.source) + + if is_complete(): + break + + print "OK" + +def comm_rank(): + while True: + data, status = mpi.world.recv(return_status=True) + if status.tag == TAG_DATA: + mpi.world.send(0, TAG_PROGRESS_REPORT, data) + data.append(mpi.rank) + if len(data) >= MAX_GENERATIONS: + dest = 0 + else: + dest = random.randrange(1, mpi.size) + mpi.world.send(dest, TAG_DATA, data) + elif status.tag == TAG_TERMINATE: + from time import sleep + mpi.world.send(0, TAG_TERMINATE, 0) + break + else: + print "[DIRECTDBG %d] unexpected tag %d from %d" % (mpi.rank, status.tag, status.source) + + +def main(): + # this program sends around messages consisting of lists of visited nodes + # randomly. After MAX_GENERATIONS, they are returned to rank 0. + + if mpi.rank == 0: + rank0() + else: + comm_rank() + + + +if __name__ == "__main__": + main() diff --git a/src/boost/libs/mpi/test/python/reduce_test.py b/src/boost/libs/mpi/test/python/reduce_test.py new file mode 100644 index 00000000..65f09f5b --- /dev/null +++ b/src/boost/libs/mpi/test/python/reduce_test.py @@ -0,0 +1,31 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test reduce() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def reduce_test(comm, generator, kind, op, op_kind, root): + if comm.rank == root: + print ("Reducing to %s of %s at root %d..." % (op_kind, kind, root)), + my_value = generator(comm.rank) + result = mpi.reduce(comm, my_value, op, root) + if comm.rank == root: + expected_result = generator(0); + for p in range(1, comm.size): + expected_result = op(expected_result, generator(p)) + assert result == expected_result + print "OK." + else: + assert result == None + return + +reduce_test(mpi.world, int_generator, "integers", lambda x,y:x + y, "sum", 0) +reduce_test(mpi.world, int_generator, "integers", lambda x,y:x * y, "product", 1) +reduce_test(mpi.world, int_generator, "integers", min, "minimum", 0) +reduce_test(mpi.world, string_generator, "strings", lambda x,y:x + y, "concatenation", 0) +reduce_test(mpi.world, string_list_generator, "list of strings", lambda x,y:x + y, "concatenation", 0) diff --git a/src/boost/libs/mpi/test/python/ring_test.py b/src/boost/libs/mpi/test/python/ring_test.py new file mode 100644 index 00000000..3c8b5b92 --- /dev/null +++ b/src/boost/libs/mpi/test/python/ring_test.py @@ -0,0 +1,42 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test basic communication. + +import boost.parallel.mpi as mpi + +def ring_test(comm, value, kind, root): + next_peer = (comm.rank + 1) % comm.size; + prior_peer = (comm.rank + comm.size - 1) % comm.size; + + if comm.rank == root: + print ("Passing %s around a ring from root %d..." % (kind, root)), + comm.send(next_peer, 0, value) + (other_value, stat) = comm.recv(return_status = True) + assert value == other_value + assert stat.source == prior_peer + assert stat.tag == 0 + else: + msg = comm.probe() + other_value = comm.recv(msg.source, msg.tag) + assert value == other_value + comm.send(next_peer, 0, other_value) + + comm.barrier() + if comm.rank == root: + print "OK" + pass + +if mpi.world.size < 2: + print "ERROR: ring_test.py must be executed with more than one process" + mpi.world.abort(-1); + +ring_test(mpi.world, 17, 'integers', 0) +ring_test(mpi.world, 17, 'integers', 1) +ring_test(mpi.world, 'Hello, World!', 'string', 0) +ring_test(mpi.world, 'Hello, World!', 'string', 1) +ring_test(mpi.world, ['Hello', 'MPI', 'Python', 'World'], 'list of strings', 0) +ring_test(mpi.world, ['Hello', 'MPI', 'Python', 'World'], 'list of strings', 1) diff --git a/src/boost/libs/mpi/test/python/scan_test.py b/src/boost/libs/mpi/test/python/scan_test.py new file mode 100644 index 00000000..193a6a44 --- /dev/null +++ b/src/boost/libs/mpi/test/python/scan_test.py @@ -0,0 +1,29 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test scan() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def scan_test(comm, generator, kind, op, op_kind): + if comm.rank == 0: + print ("Prefix reduction to %s of %s..." % (op_kind, kind)), + my_value = generator(comm.rank) + result = mpi.scan(comm, my_value, op) + expected_result = generator(0); + for p in range(1, comm.rank+1): + expected_result = op(expected_result, generator(p)) + + assert result == expected_result + if comm.rank == 0: + print "OK." + return + +scan_test(mpi.world, int_generator, "integers", lambda x,y:x + y, "sum") +scan_test(mpi.world, int_generator, "integers", lambda x,y:x * y, "product") +scan_test(mpi.world, string_generator, "strings", lambda x,y:x + y, "concatenation") +scan_test(mpi.world, string_list_generator, "list of strings", lambda x,y:x + y, "concatenation") diff --git a/src/boost/libs/mpi/test/python/scatter_test.py b/src/boost/libs/mpi/test/python/scatter_test.py new file mode 100644 index 00000000..e0bad967 --- /dev/null +++ b/src/boost/libs/mpi/test/python/scatter_test.py @@ -0,0 +1,36 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test scatter() collective. + +import boost.parallel.mpi as mpi +from generators import * + +def scatter_test(comm, generator, kind, root): + if comm.rank == root: + print ("Scattering %s from root %d..." % (kind, root)), + + if comm.rank == root: + values = list() + for p in range(0, comm.size): + values.append(generator(p)) + result = mpi.scatter(comm, values, root = root) + else: + result = mpi.scatter(comm, root = root); + + assert result == generator(comm.rank) + + if comm.rank == root: print "OK." + return + +scatter_test(mpi.world, int_generator, "integers", 0) +scatter_test(mpi.world, int_generator, "integers", 1) +scatter_test(mpi.world, gps_generator, "GPS positions", 0) +scatter_test(mpi.world, gps_generator, "GPS positions", 1) +scatter_test(mpi.world, string_generator, "strings", 0) +scatter_test(mpi.world, string_generator, "strings", 1) +scatter_test(mpi.world, string_list_generator, "list of strings", 0) +scatter_test(mpi.world, string_list_generator, "list of strings", 1) diff --git a/src/boost/libs/mpi/test/python/skeleton_content_test.cpp b/src/boost/libs/mpi/test/python/skeleton_content_test.cpp new file mode 100644 index 00000000..7ccae00e --- /dev/null +++ b/src/boost/libs/mpi/test/python/skeleton_content_test.cpp @@ -0,0 +1,37 @@ +// (C) Copyright 2006 Douglas Gregor <doug.gregor -at- gmail.com> + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor + +#include <boost/parallel/mpi/python.hpp> +#include <boost/python.hpp> +#include <boost/serialization/list.hpp> +using namespace boost::python; + +template<typename T> +boost::python::list list_to_python(const std::list<T>& value) { + boost::python::list result; + for (typename std::list<T>::const_iterator i = value.begin(); + i != value.end(); ++i) + result.append(*i); + return result; +} + +BOOST_PYTHON_MODULE(skeleton_content) +{ + using boost::python::arg; + + class_<std::list<int> >("list_int") + .def("push_back", &std::list<int>::push_back, arg("value")) + .def("pop_back", &std::list<int>::pop_back) + .def("reverse", &std::list<int>::reverse) + .def(boost::python::self == boost::python::self) + .def(boost::python::self != boost::python::self) + .add_property("size", &std::list<int>::size) + .def("to_python", &list_to_python<int>); + + boost::parallel::mpi::python::register_skeleton_and_content<std::list<int> >(); +} diff --git a/src/boost/libs/mpi/test/python/skeleton_content_test.py b/src/boost/libs/mpi/test/python/skeleton_content_test.py new file mode 100644 index 00000000..1dfde3cf --- /dev/null +++ b/src/boost/libs/mpi/test/python/skeleton_content_test.py @@ -0,0 +1,75 @@ +# Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. + +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Test skeleton/content + +import boost.parallel.mpi as mpi +import skeleton_content + +def test_skeleton_and_content(comm, root, manual_broadcast = True): + assert manual_broadcast + + # Setup data + list_size = comm.size + 7 + original_list = skeleton_content.list_int() + for i in range(0,list_size): + original_list.push_back(i) + + if comm.rank == root: + # Broadcast skeleton + print ("Broadcasting integer list skeleton from root %d..." % (root)), + if manual_broadcast: + for p in range(0,comm.size): + if p != comm.rank: + comm.send(p, 0, value = mpi.skeleton(original_list)) + print "OK." + + # Broadcast content + print ("Broadcasting integer list content from root %d..." % (root)), + if manual_broadcast: + for p in range(0,comm.size): + if p != comm.rank: + comm.send(p, 0, value = mpi.get_content(original_list)) + + print "OK." + + # Broadcast reversed content + original_list.reverse() + print ("Broadcasting reversed integer list content from root %d..." % (root)), + if manual_broadcast: + for p in range(0,comm.size): + if p != comm.rank: + comm.send(p, 0, value = mpi.get_content(original_list)) + + print "OK." + else: + # Allocate some useless data, to try to get the addresses of + # the underlying lists used later to be different across + # processors. + junk_list = skeleton_content.list_int() + for i in range(0,comm.rank * 3 + 1): + junk_list.push_back(i) + + # Receive the skeleton of the list + if manual_broadcast: + transferred_list_skeleton = comm.recv(root, 0) + assert transferred_list_skeleton.object.size == list_size + + # Receive the content and check it + transferred_list = transferred_list_skeleton.object + if manual_broadcast: + comm.recv(root, 0, mpi.get_content(transferred_list)) + assert transferred_list == original_list + + # Receive the content (again) and check it + original_list.reverse() + if manual_broadcast: + comm.recv(root, 0, mpi.get_content(transferred_list)) + assert transferred_list == original_list + + +test_skeleton_and_content(mpi.world, 0) +test_skeleton_and_content(mpi.world, 1) |