![]() |
MC#: Frequently asked questions (FAQ) |
|
[ Ðóññêàÿ âåðñèÿ ñòðàíèöû ]
[ Version for printing ]
?
Today we have hundreds of
different programming languages. Why do we need one more language? ?
What's the difference between
asynchronous and synchronous methods?. ?
How can I execute function on
remote machine/node? ?
How can I return results to
the main function from movable method?. ?
How can I pass some values to
movable method that has already been launched? What's MC# stand for?Multiprocessor C# Today we have hundreds of different programming languages. Why do we need one more language?
MC# language allows write parallel concurrent programs on extension of such
high-level programming language as C#. By design programs written in MC#
language can work in both local and distributed modes (on cluster/GRID-network/…).
The language itself abstracts programmer’s mind from the physical platform
where his program will be executed in the future. Actually, when programmer is
writing a program, he shouldn’t exactly know how many processors will be used
by his program or which configuration will be used. All he needs to do is to
mark methods, which should be executed on other processors/computers in
parallel as “movable” and all low-level tasks such as moving complex memory
objects from one node to another one, load balancing and etc. should be done by
Runtime System. What's the difference between asynchronous and synchronous methods?Synchronous method
- is a conventional method. When you
call such method you have to wait until some result is returned. In C#, conventional methods are synchronous: the caller waits until the
method called is completed, and then continues its work. In the world of
parallel computations, reduction of execution time of a program is achieved by
transferring some methods for execution to different processors, after that a
program which transferred these methods immediately proceeds to the next
instructions. Methods that commonly are scheduled for execution in the
different threads within single computer are called asynchronous (in Polyphonic
C#) and they are declared by using the async
keyword:
The specific of these methods is that their call completes essentially immediately. We should note here, that async keyword is a subtype of void type, i.e. it doesn't return any value. However, the results computed by asynchronous function can be returned through its parameters, global variables or by using the out keyword. Here's the example of using asynchronous functions:
How can I execute function on remote machine/node?All you need to do is to mark it with movable keyword. For example:
In this example we create object t
of type Test and then we launch movable-function
remoteFun and pass the current system
time as a parameter. As you can see, you can assign as movable function’s parameters
objects of almost any .Net built-in types as well as objects of your own types.
Actually, movable functions can accept as parameters objects of any classes which
implement interface ISerializable. All base
classes in .Net, like long, int, DateTime, string, etc. and more complicated (like Bitmap) already support this interface. The launch of movable function completes almost immediately
(asynchronously). If your program is executed in local mode, then this function
will be launched in new thread. If distributed mode is applied then one of the cluster
nodes will be used. That’s why there is a special Console.ReadLine()
at the end of the program – otherwise program will finish executing even before
the movable method remoteFun is
started. How can I return results to the main function from movable method?Movable methods itself cannot return any values/objects directly. To
simplify the things you can think that movable
keyword is a synonym for void, but keeping in
mind that movable methods can be executed on local as well as on any other
processor (node, cluster) in current computational network. To return results from
movable methods and to exchange data between different movable methods you
should use channels (Channel). Here is the code
example of using channels:
In this example we create an object of type Test2,
which has resultChannel channel
defined. This channel accepts only objects of type DateTime.
When new object of type DateTime arrives it is
displayed to the system console. Movable method remoteFun accept as a parameter a channel called result. This channel also can accept
only DateTime objects. Every second this movable
method sends new timestamp using this channel until Enter or Return keyboard button
is pressed. I need to wait for results that are being calculated in movable function to be ready. How can I do this in MC#?MC# language uses bounds (or “chords”, in terminology of Polyphonic C#)
to accomplish such tasks. Bounds combine synchronous methods, asynchronous
methods (in theory… currently async keyword is not supported by MC# compiler yet)
and channels with the help of ‘&’ symbol and serves as a synchronization
mechanism in MC#. General rule of chord definition: Chord consists of only one body, not more than
one synchronous method and at least one asynchronous method or channel. The body of the chord is executed only when all methods declared in the
chord were called (or accordingly the messages arrived in the bounded channels).
The body of the chord must return the result of the same type as return type of
synchronous method in this particular chord. Example of chord definition:
In this example channel result
and synchronous method Get are
bounded in the chord. The body of the chord contains only one operator which
returns the value object arrived to the channel result. When method Get is called the following
condition is checked: is there any new message in channel result? If there is no new message, then current thread (in context
of this thread method Get was called)
is suspended until new message won’t arrive. When new message will arrive this
thread will be resumed and the body of the chord will be executed (this message
won’t be added to channel’s queue). If there were already some messages in the channel result when method Get
was called then the body of the chord will be executed immediately (and one
message will be read and pushed from the channel’s queue). From the other hand, when message arrives in channel result and method Get hasn’t been called yet then this message is queued for “future
use”. As soon as method Get is called
message is read and pushed from this queue. But in case if when message arrived method Get had already been called then the body of the chord is executed
(and the message is considered to be read and not queued in channel’s queue). How can I pass some values to movable method that has already been launched?There is a special bidirectional channel class in MC# called BDChannel. Generally you
can only send messages to conventional channels by calling Send method, while the reading from the channel occurs only when the
corresponding chord is triggered. Bidirectional channels support writing
operation (Send) as well as reading
operation (Receive). Example of using bidirectional channels:
This example shows how two movable functions can exchange the data amongst
themselves (simple ping-pong game). It should print the following phrases 100
times:
And exactly in this order – first goes ping…, then goes pong…. © J The particular feature of bidirectional channels is that they are being
registered on the same node where they were initially created. If you apply
bidirectional channels to movable methods then proxies of these channels will
be passed, but not the copies of channels (as it happens with all other types
of objects). When you call Send or Receive methods of such “proxies”, the method
call is actually transferred to the node where the channel was initially
registered. That means that if you send some object through bidirectional
channel from node B this object is
transferred to the node of initial registration A, where it is put on top of the channel’s queue. And if you will
try to read from the channel by calling Receive
method of the same channel on node B
then the reading request will be transferred to the node A. Remote call of the method is quite expensive operation in any system (from
the point of view of performance). This should be kept in mind when using
bidirectional channels. For example, the performance of previous example can be
improved by minimizing the number of remote function calls in the following way:
In this example two movable methods ping
and pong first of all exchange
bidirectional channels among themselves (they will use these “exchanged
channels” in future for data exchange). Channel bdc3 is registered on the same node where movable method ping is being executed, and bdc4 is registered on the same node
where movable method pong is being
executed, and that’s why the number of remote communications in this example is
almost two times less than in the previous example. You can find complete working sources of this example in folder “examples/pingpong/” after installing
distribution package. I need to execute some action on remote node when new message
arrives in bidirectional channel. How can I achieve this?
In MC# language there is a special support of Activities to accomplish
such kind of tasks. Activity
– is a special class that can listen to bidirectional channels and perform some
actions when new messages arrive in these channels. Activity can subscribe to several
channels simultaneously, and one bidirectional channel can be listened to by several
Activities at the same time. To create your own activity you must define new
activity class, inherit it from class MCSharp.Activity
and override method Run. This method is called when new message arrives to one
of the subscribed channels. Then you can create an instance of your activity
class and register it on the channels that must be listened to. Example of
using Activities:
If you run this sample it should print:
And if you press Enter (or Return) button on your keyboard until all 100
messages are printed then myActivity
object will be unregistered and there can be a situation when bdc channel still has some unread messages
in the queue. Is there in MC# any analogue of MPI functions MPI_iSum, MPI_fMax, etc., that allow one to calculate some summary characteristics for values being produced on numerous nodes (such as sum, average, maximum, minimum)?For this purpose there do exists a special class called BlackBoard. With the help of this class you can
calculate the following functions: Sum,
Max, Min, Avg and Count. To use this class you need to follow the next steps: first of all create
an object of type BlackBoard. Constructor of BlackBoard class accepts an
integer as a parameter – number of processors, each of which will produce some
values for aggregation.
Then you can pass this object as a parameter to movable functions and
move them to other nodes:
Afterwards you need to initialize bb
(by calling Initialize method):
During the execution of this method Runtime System exchanges the
channels between main node, where initially object bb was created, and other nodes. This is made for the sake of
optimization. Also you need to initiate bb
on all other nodes like this:
Class BlackBoard has a method called Send(double)
for sending messages:
Aggregation of values (i.e. calculation of summary, maximum and minimum
values and so on) is made on the node where BlackBoard
object was initially created. This aggregation is made as soon as at least one
value will be accepted from all launched movable methods that accepted copy of bb as parameter. Actually that means that
every node can first of all send some values and then receive the same number
of aggregated statistics at one time. In order to wait for the aggregation statistics to be ready you can use
the method Wait. It should be used
every time when you need to use properties Sum,
Max, Min, Avg, Count:
If you don’t call the Wait
method then you will get the same values… These values will be the same as in
the first iteration of the cycle. The complete example of using BlackBoard
you can find after installing the distributive in folder “examples/blackboard”. |
|