Intel® Moderncode for Parallel Architectures
Support for developing parallel programming applications on Intel® Architecture.

IDS Thread Synchronization Article

ClayB
New Contributor I
428 Views
Found a new threading article on the Intel Developer Services Home page:"Multithreading for Experts: Inside a Parallel Application."
The title is misleading since the article deals with methods of waking threads on demand with and without standard synchronization objects. There is some analysis of timing and comparison between methods.

Any comments or discussion?
--clay
0 Kudos
3 Replies
jseigh
Beginner
428 Views
From a quick scan of the article, I'm guessing they're trying to figure out the most efficient way to implement the barrier synchronization object on windows if the APC stuff is a clue.

APC has one minor problem in that it uses callbacks which means you want to use a language that supports closures if you want the parallel sections to appear inline in the code.

In general, if you have code that is going to signal individual threads, you are going to have the problem of synchronizing a collective data structure with a lock, and of serial signaling. Both are bottlenecks.

Since this is windows, I'd go with a barrier implemented with 2 windows Event objects. You can implment it lock-free. It's fairly simple. I can post the pseudocode if anyone's interested.

Joe Seigh
0 Kudos
jseigh
Beginner
429 Views
Here's some code of the top of my head. It compiles but hasn't been tested.


#define _WIN32_WINNT 0x0500
#include
#include


typedef struct {
LONG waitCount;
LONG initCount;
int ndx; // index of active Event
HANDLE hEvent[2];
} barrier_t;


//---------------------------------------------------------------
// BarrierInit -- initialize barrier synchronization object
// count is the number of waiters using barrier
//
//---------------------------------------------------------------
DWORD BarrierInit(barrier_t *barrier, LONG count) {

if (count = 0)
return 1; // error

barrier->initCount = count;
barrier->waitCount = count;
barrier->ndx = 0;
// create 2 manually resettable events in non-signaled state
barrier->hEvent[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
barrier->hEvent[1] = CreateEvent(NULL, TRUE, FALSE, NULL);

return 0;
}

//---------------------------------------------------------------
// BarrierDestroy --
//
//---------------------------------------------------------------
DWORD BarrierDestroy(barrier_t *barrier) {
CloseHandle(barrier->hEvent[0]);
CloseHandle(barrier->hEvent[1]);

return 0;
}

//---------------------------------------------------------------
// BarrierWait -- wait on barrier w/ autoreset of barrier
//
//---------------------------------------------------------------
DWORD BarrierWait(barrier_t *barrier) {
int ndx;

ndx = barrier->ndx; // do this *before* decrement of waitcount!!

if (InterlockedDecrement(&(barrier->waitCount)) == 0) {
barrier->waitCount = barrier->initCount; // reset wait count
barrier->ndx = 1 - ndx; // toggle index to next event
ResetEvent(barrier->hEvent[barrier->ndx]); // reset next Event
SetEvent(barrier->hEvent[ndx]); // set (signal) current Event

}

else
WaitForSingleObject(barrier->hEvent[ndx], INFINITE);

return 0;

}

/*-*/


Of course it looks much better if the leading whitespace is preserved and the code is not wrapped.


Joe Seigh

(the stuff I'm really working on)
Atomic Ptr Plus
0 Kudos
ClayB
New Contributor I
429 Views
Joe -
Thanks for the code.
I'm going to have to reread the article, but I thought the object was to devise a means to set up a "conditional wait" synchronization for Win32 threads like that found in Pthreads. I didn't think it was to have a barrier, except to allow multiple threads to be released on signal. More like a semaphore than a barrier.
As I said, I was concentrating on other things and will need to go back over the article to see exactly what the authors were attempting.
--clay
0 Kudos
Reply