examples: add a basic usage of mpi
[nit.git] / examples / mpi / src / mpi_simple.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 module mpi_simple
18
19 import mpi
20
21 # Simple class transfered between processors
22 class ProcessorInfo
23 auto_serializable
24 super Serializable
25
26 var rank: Int
27 var size: Int
28 var name: String
29 var string_of_random_length: String
30
31 init(mpi: MPI)
32 do
33 self.rank = comm_world.rank.to_i
34 self.size = comm_world.size
35 self.name = mpi.processor_name
36 self.string_of_random_length = "+" * 10.rand
37 end
38
39 redef fun to_s do return "<{name}: {rank}/{size} {string_of_random_length}>"
40 end
41
42 var mpi = new MPI
43
44 var data = new CIntArray(2)
45 if comm_world.size == 1 then
46 print "not enough nodes, got only 1"
47 mpi.finalize
48 exit 1
49 end
50
51 print "stdout: processor '{mpi.processor_name}' {comm_world.rank}/{comm_world.size}"
52
53 if comm_world.rank == 0.rank then
54 # send - ints
55 data[0] = 123
56 data[1] = 456
57 mpi.send_from(data, 0, 2, 1.rank, 0.tag, comm_world)
58
59 # send - simple string
60 mpi.send_all("Hello", 1.rank, 0.tag, comm_world)
61 mpi.send_from(" World", 0, 6, 1.rank, 0.tag, comm_world)
62 mpi.send_from("+-!0?", 2, 2, 1.rank, 0.tag, comm_world)
63 else if comm_world.rank == 1.rank then
64
65 # recv - ints
66 mpi.recv_into(data, 0, 2, 0.rank, 0.tag, comm_world)
67 print "received data: {data[0]} {data[1]}"
68
69 # recv - simple string
70 var buf = new FlatBuffer.with_capacity(5)
71 mpi.recv_fill(buf, 0.rank, 0.tag, comm_world)
72 print "received string: {buf}"
73
74 mpi.recv_into(buf, 5, 6, 0.rank, 0.tag, comm_world)
75 print "received string: {buf}"
76
77 mpi.recv_into(buf, 3, 2, 0.rank, 0.tag, comm_world)
78 print "received string: {buf}"
79 end
80
81 # Passing complex objects and inverse sender/receiver
82 if comm_world.rank == 0.rank then
83 var errors = 0
84 var processors_per_host = new HashMap[String, Int]
85
86 # recv - serializable
87 for p in [1 .. comm_world.size[ do
88 var a = mpi.recv(new Rank.any, 0.tag, comm_world)
89 print "received serialized: {a or else "<null>"}"
90
91 if a != null and a isa ProcessorInfo then
92 if not processors_per_host.keys.has(a.name) then
93 processors_per_host[a.name] = 1
94 else processors_per_host[a.name] += 1
95 else errors += 1
96 end
97
98 print "errors: {errors}"
99 print "processors: {processors_per_host.join(", ", ": ")}"
100 else
101 # send - serializable
102 srand_from comm_world.rank.to_i
103 var a = new ProcessorInfo(mpi)
104 mpi.send(a, 0.rank, 0.tag, comm_world)
105 end
106
107 mpi.finalize