Let's say i have a MPI process_0 waiting for messages from two different processess (process_1 and process_2). Something like this:
...
MPI_Recv(&message_1, 1, MPI_INT, process_1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Recv(&message_2, 1, MPI_INT, process_2, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
...
Imagine the scenario where when process_2 sends it's message, to process_0, before process_1. What happens then?
I guess process_0 must recieve the message from process_1 before it can read the message from process_2?
What happens att the send function at process_2? Will it be stuck at the send function trying to deliver the message until process_0 can receive it? Or will it send the message not caring if process_0 has received it or not and continue running the consecutive code after the send function?
According to the MPI standard, a correct program should always assume a blocking send (e.g. MPI_Send()) will block until a matching receive is posted.
Note that if the message is short enough (depending on your MPI implementation, your interconnect and other factors), it might be sent in eager mode and MPI_Send() will return immediately. If your MPI implementation features a progress thread, MPI_Send() might also return before a matching receive is posted. That being said, you should not assume this is a behavior mandated by the standard, and if you want to write portable code, you should assume MPI_Send() will always block until a matching receive is posted.
Related
So I am trying to understand the message processing code of Unreal Engine on Windows OS, and I didn't find any frequent usage of the function MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx in the message pumping code.
The engine message pumping goes like this:
MSG Message;
// standard Windows message handling
while(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
For context, this code will run every frame one to three times, meaning the code will be executed each 2 - 5 milliseconds on average throughout the running time of the application. A) Does that make wait functions unnecessary? or am I missing something here!
B) Is there any rough estimation of how long an application could be busy doing 'other stuff' before processing incoming messages? For instance if an application only processes messages every 50 millisecond, is that a bad practice? or is that a reasonable way of doing it? And what if the period became 500 milliseconds and so?
Use MsgWaitForMultipleObjects/etc if you need to both handle window message processing and kernel handle or alertable waits in a single thread. If you are only doing message processing then simply use a normal GetMessage based message loop, if only doing kernel handle or alertable waits then use WaitForMultipleObjects as appropriate.
I am working on a project that uses MPI routines and multiple threads for sending and receiving messages. I would like each receiving thread to focus on a different incoming message instead of having two or more trying to receive the same one. Is there a way to achieve this?
I don't know if this helps but I am currently using Iprobe() to check for incoming messages and Irecv() with Test() to check if the thread has received the whole message.
Starting with version 3 of the standard, MPI allows for the removal of matched messages from the message queue so that they are no longer visible to subsequent probes/receives. This is done using the so-called matched probes. Just replace MPI_Iprobe with MPI_Improbe, which is the non-blocking matched probe operation:
int flag;
MPI_Status status;
MPI_Message msg;
MPI_Improbe(source, tag, comm, &flag, &msg, &status);
Once MPI_Improbe returns 1 in flag, a message matching (source, tag, comm) has arrived. A handle to the message is stored into msg and the message is removed from the queue. Subsequent probes or receives with a matching (source, tag, comm) triplet - by the same thread or in another - won't see the same message again and therefore won't interfere with its reception by the thread that matched it originally.
To receive a matched message, use MPI_Imrecv (or the blocking MPI_Mrecv):
MPI_Request req;
MPI_Imrecv(buffer, count, dtype, &msg, &req);
do
{
...
MPI_Test(&req, &flag, &status);
}
while (!flag);
Versions of MPI before 3.0 do not provide similar functionality. But, if I understand you correctly, you only need to guarantee that no matching probe will be posted before MPI_Irecv has had the opportunity to remove the message from the queue (which is what matched probe+receive is meant to prevent). If you are probing in a master thread and then dispatching the messages to different threads, then you could use a semaphore to delay the execution of the next probe by the main thread until after the worker has issued MPI_Irecv. If you have multiple threads doing probe+receive, then you may simply issue the MPI_Irecv call in the same critical section (or whatever synchronisation primitive you use to achieve the serialisation of the MPI calls as required by MPI_THREAD_SERIALIZED) as MPI_Iprobe once the probe turns out successful:
// Worker thread
CRITICAL(mpi)
{
MPI_Iprobe(source, tag, comm, &flag, &status);
if (flag)
MPI_Irecv(buffer, count, dtype, status.MPI_SOURCE, status.MPI_TAG, comm, &req);
}
Replace the CRITICAL(name) { ... } notation with whatever primitives your programming environment provides.
If I understand you correctly it's not the matter how you receive messages but how you send them. As you can see below MPI_Send function has destination parameter which defines to which thread this message will be sent.
MPI_Send(
void* data,
int count,
MPI_Datatype datatype,
int destination,
int tag,
MPI_Comm communicator)
So if you wan to make certain threads receive certain messages you have to send this messages only to that thread.
I have a simple tunnel program that needs to simultaneously block on standard input and a socket. I currently have a program that looks like this (error handling and boiler plate stuff omitted):
HANDLE host = GetStdHandle(STD_INPUT_HANDLE);
SOCKET peer = ...; // socket(), connect()...
WSAEVENT gate = WSACreateEvent();
OVERLAPPED xfer;
ZeroMemory(&xfer, sizeof(xfer));
xfer.hEvent = gate;
WSABUF pbuf = ...; // allocate memory, set size.
// start an asynchronous transfer.
WSARecv(peer, &pbuf, 1, 0, &xfer, 0);
while ( running )
{
// wait until standard input has available data or the event
// is signaled to inform that socket read operation completed.
HANDLE handles[2] = { host, gate };
const DWORD which = WaitForMultipleObjects
(2, handles, FALSE, INFINITE) - WAIT_OBJECT_0;
if (which == 0)
{
// read stuff from standard input.
ReadFile(host, ...);
// process stuff received from host.
// ...
}
if (which == 1)
{
// process stuff received from peer.
// ...
// start another asynchronous transfer.
WSARecv(peer, &pbuf, 1, 0, &xfer, 0);
}
}
The program works like a charm, I can transfer stuff through this tunnel program without a hitch. The thing is that it has a subtle bug.
If I start this program in interactive mode from cmd.exe and standard input is attached to the keyboard, pressing a key that does not produce input (e.g. the Ctrl key) makes this program block and ignore data received on the socket. I managed to realize that this is because pressing any key signals the standard input handle and WaitForMultipleObjects() returns. As expected, control enters the if (which == 0) block and the call to ReadFile() blocks because there is no input available.
Is there a means to detect how much input is available on a Win32 stream? If so, I could use this to check if any input is available before calling ReadFile() to avoid blocking.
I know of a few solutions for specific types of streams (notably ClearCommError() for serial ports and ioctlsocket(socket,FIONBIO,&count) for sockets), but none that I know of works with the CONIN$ stream.
Use overlapped I/O. Then test the event attached to the I/O operation, instead of the handle.
For CONIN$ specifically, you might also look at the Console Input APIs, such as PeekConsoleInput and GetNumberOfConsoleInputEvents
But I really recommend using OVERLAPPED (background) reads wherever possible and not trying to treat WaitForMultipleObjects like select.
Since the console can't be overlapped in overlapped mode, your simplest options are to wait on the console handle and use ReadConsoleInput (then you have to process control sequences manually), or spawn a dedicated worker thread for synchronous ReadFile. If you choose a worker thread, you may want to then connect a pipe between that worker and the main I/O loop, using overlapped pipe reads.
Another possibility, which I've never tried, would be to wait on the console handle and use PeekConsoleInput to find out whether to call ReadFile or ReadConsoleInput. That way you should be able to get non-blocking along with the cooked terminal processing. OTOH, passing control sequences to ReadConsoleInput might inhibit the buffer-manipulation actions they were supposed to take.
If the two streams are processed independently, or nearly so, it may make more sense to start a thread for each one. Then you can use a blocking read from standard input.
Most of the Win32 main loops I've seen are all structured like:
while (GetMessage(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message);
DispatchMessage(&message);
}
It was pointed out to me that MsgWaitForMultipleObjects may be used to add some variety to a main loop. But is there a scenario where doing something between GetMessage, TranslateMessage and DispatchMessage is actually useful?
The more traditional message loop looks like this:
while (GetMessage(&msg, 0, 0, 0))
{
if (!TranslateAccelerator(hwndMain, haccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
It is a pretty big hint to what you'd want to do before dispatching the message: catch messages that ought to be intercepted and treated specially before the window sees them. Keyboard shortcuts are a classic example, they need to be detected no matter what window has the focus.
Any GUI class library exposes it with a virtual method named something like App.PreProcessMessage, a virtual function that can be overridden so your program can implement its own shortcuts and whatnot.
They are different beasts.
For TranslateMessage function
Translates virtual-key messages into
character messages. The character
messages are posted to the calling
thread's message queue, to be read the
next time the thread calls the
GetMessage or PeekMessage function.
[...]
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
DispatchMessage, on the other hand, dispatches a message to a window procedure.
So DispatchMessage does the actual work of processing the message. TranslateMessage MAY or MAY NOT post a new message to the thread queue. If the message is translated then a character message is posted to the thread's message queue.
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
They are separate calls so you, the programmer, can have a chance to avoid the message translation provided by TranslateMessage.
Well to quote an example from the MSDN:
You can modify a message loop in a variety of ways. For example, you can retrieve messages from the queue without dispatching them to a window. This is useful for applications that post messages not specifying a window. You can also direct GetMessage to search for specific messages, leaving other messages in the queue. This is useful if you must temporarily bypass the usual FIFO order of the message queue.
You can also possibly avoid calls to Translate message if you don't need to convert keyboard input control codes.
TranslateMessage() converts virtual keys messages to character input messages.
It is a separate call for the remote chance that under certain circumstances you would want to not produce character input messages for certain virtual keys.
I'm interested in the behavior of send function when using a blocking socket.
The manual specifies nothing about this case explicitly.
From my tests (and documentation) it results that when using send on a blocking socket I have 2 cases:
all the data is sent
an error is returned and nothing is sent
In lines of code (in C for example) this translate like this:
// everything is allocated and initilized
int socket_fd;
char *buffer;
size_t buffer_len;
ssize_t nret;
nret = send(socket_fd, buffer, buffer_len, 0);
if(nret < 0)
{
// error - nothing was sent (at least we cannot assume anything)
}
else
{
// in case of blocking socket everything is sent (buffer_len == nret)
}
Am I right?
I'm interested about this behavior on all platforms (Windows, Linux, *nix).
From the man page. (http://linux.die.net/man/2/send)
"On success, these calls return the number of characters sent. On error, -1 is returned, and errno is set appropriately. "
You have three conditions.
-1 is a local error in the socket or it's binding.
Some number < the length: not all the bytes were sent. This is usually the case when the socket is marked non-blocking and the requested operation would block; the errno value is EAGAIN.
You probably won't see this because you're doing blocking I/O.
However, the other end of the socket could close the connection prematurely, which may lead to this. The errno value would probably be EPIPE.
Some number == the length: all the bytes were sent.
My understanding is that a blocking send need not be atomic, see for example the Solaris send man page:
For socket types such as SOCK_DGRAM and SOCK_RAW that require atomic messages,
the error EMSGSIZE is returned and the message is not transmitted when it is
too long to pass atomically through the underlying protocol. The same
restrictions do not apply to SOCK_STREAM sockets.
And also look at the EINTR error code there:
The operation was interrupted by delivery of a signal before any data could
be buffered to be sent.
Which indicates that send can be interrupted after some data has been buffered to be sent - but in that case send would return the number of bytes that have already been buffered to be sent (instead of an EINTR error code).
In practice I would only expect to see this behaviour for large messages (that can not be handled atomically by the operating system) on SOCK_STREAM sockets.