SMP basics

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Richard Allbert
Posts: 792
Joined: Wed Jul 19, 2006 9:58 am

SMP basics

Post by Richard Allbert »

Hi,

I'd like (eventually) to implement parallel search.

I've been spending some time looking at threads, and have made a very simple program (basically like on the MSDN site) to create threads and initialise them...

Code: Select all



#define MAX_THREADS 3
#define BUF_SIZE 255

using namespace std;


DWORD WINAPI Thread_Init( LPVOID input );


typedef struct sMyPosition {
    int alpha;
    int beta;
    int board[64];
} MYPOS, *PMYPOS;

MYPOS PosArray[MAX_THREADS];
DWORD   dwThreadIdArray[MAX_THREADS];
HANDLE  hThreadArray[MAX_THREADS];


int main()
{

    // Create MAX_THREADS worker threads.

    for&#40; int i=0; i<MAX_THREADS; i++ )
    &#123;
       // Generate unique data for each thread to work with.
        PosArray&#91;i&#93;.alpha = i-10000;
        PosArray&#91;i&#93;.beta = i+10000;

        // Create the thread to begin execution on its own.

        hThreadArray&#91;i&#93; = CreateThread&#40;
            NULL,                   // default security attributes
            0,                      // use default stack size
            Thread_Init,       // thread function name
            &PosArray&#91;i&#93;,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadIdArray&#91;i&#93;);   // returns the thread identifier


        // Check the return value for success.
        // If CreateThread fails, terminate execution.
        // This will automatically clean up threads and memory.

        if &#40;hThreadArray&#91;i&#93; == NULL&#41;
        &#123;
           ExitProcess&#40;3&#41;;
        &#125;
    &#125; // End of main thread creation loop.

    // Wait until all threads have terminated.

    WaitForMultipleObjects&#40;MAX_THREADS, hThreadArray, TRUE, INFINITE&#41;;

    for&#40;int i=0; i<MAX_THREADS; i++)
    &#123;
        CloseHandle&#40;hThreadArray&#91;i&#93;);
    &#125;

    return 0;
&#125;


DWORD WINAPI Thread_Init&#40; LPVOID input )
&#123;
    PMYPOS pData;
    pData = &#40;PMYPOS&#41;input;
    printf&#40;"\n Creating... ");
    printf&#40;"Parameters = %d, %d\n",pData->alpha, pData->beta&#41;;

    return 0;
&#125;

I have read up on all the deinfitions above, and understand it.

What I'm really struggling with is the concept of setting the threads "doing" something in parallel.

What I had in mind was a simple function that prints output at random intervals from each thread, so I can see the evidence of the parallel computing.

But how do I do this? I couldn't find much on MSDN.... it's hard enough to undertand as it is :)

Thanks for any replies!!!
Gian-Carlo Pascutto
Posts: 1243
Joined: Sat Dec 13, 2008 7:00 pm

Re: SMP basics

Post by Gian-Carlo Pascutto »

If you just change Thread_Init in the above code to print in a loop you already have it...
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: SMP basics

Post by Sven »

Richard Allbert wrote:What I'm really struggling with is the concept of setting the threads "doing" something in parallel.

What I had in mind was a simple function that prints output at random intervals from each thread, so I can see the evidence of the parallel computing.

But how do I do this? I couldn't find much on MSDN.... it's hard enough to undertand as it is :)

Thanks for any replies!!!
You make the threads "doing" something by just creating them. The operating system will care about assigning CPU time to each thread appropriately, which of course is also influenced by things like priority, or whether a thread is currently computing or doing I/O.

Just like the main() function is somehow "magically" called when starting a new process, it is the function that you specified as a new thread's "starting point" (in your case, Thread_Init()) that is automatically called for each thread as soon as it gets the CPU the first time. As soon as that function returns, the thread is ready to terminate and will go away either by being waited for or by being killed (or similar).

Maybe you want to extend your first example of Thread_Init() by inserting the current thread ID, or something that uniquely identifies each single thread, into any output that is written, so that you get a better impression about who does what and (by adding a time stamp) also when.

Sven
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: SMP basics

Post by bob »

When you create a thread, you tell it to start in "thread_init" in your code.

Duplicate that code instead, so that you have two blocks of code, each of which creates a thread. Make the first one call "thread_init1" (or whatever you want to call it). Make the second one call "thread_init2". Write those two functions and have each do something different. For example, have one sleep for 5 seconds and then print "hello from thread 1" while the other sleeps for 2 seconds and prings "hello from thread 2"...

That will give you a basic idea of how the two threads execute in parallel.
Richard Allbert
Posts: 792
Joined: Wed Jul 19, 2006 9:58 am

Re: SMP basics

Post by Richard Allbert »

:shock:

Ok, that was easier than expected.

Code: Select all



#define MAX_THREADS 3
#define BUF_SIZE 255

using namespace std;


DWORD WINAPI Thread_Init1&#40; LPVOID input );
DWORD WINAPI Thread_Init2&#40; LPVOID input );


typedef struct sMyPosition &#123;
    int alpha;
    int beta;
    int board&#91;64&#93;;
&#125; MYPOS, *PMYPOS;

MYPOS PosArray&#91;MAX_THREADS&#93;;
DWORD   dwThreadIdArray&#91;MAX_THREADS&#93;;
HANDLE  hThreadArray&#91;MAX_THREADS&#93;;

int main&#40;)
&#123;
    int usenum = 2;

    // Create MAX_THREADS worker threads.

    for&#40; int i=0; i<usenum; i++ )
    &#123;
       // Generate unique data for each thread to work with.
        PosArray&#91;i&#93;.alpha = i-10000;
        PosArray&#91;i&#93;.beta = i+10000;

        // Create the thread to begin execution on its own.
        if&#40;i==0&#41;
        hThreadArray&#91;i&#93; = CreateThread&#40;NULL, 0, Thread_Init1,&PosArray&#91;i&#93;,0, &dwThreadIdArray&#91;i&#93;);   // returns the thread identifier
        else if&#40;i==1&#41;
        hThreadArray&#91;i&#93; = CreateThread&#40;NULL, 0, Thread_Init2,&PosArray&#91;i&#93;,0, &dwThreadIdArray&#91;i&#93;);
        // Check the return value for success.
        // If CreateThread fails, terminate execution.
        // This will automatically clean up threads and memory.

        if &#40;hThreadArray&#91;i&#93; == NULL&#41;
        &#123;
           ExitProcess&#40;3&#41;;
        &#125;
    &#125; // End of main thread creation loop.

    // Wait until all threads have terminated.

    WaitForMultipleObjects&#40;usenum, hThreadArray, TRUE, INFINITE&#41;;

    for&#40;int i=0; i<usenum; i++)
    &#123;
        CloseHandle&#40;hThreadArray&#91;i&#93;);
    &#125;

    return 0;
&#125;


DWORD WINAPI Thread_Init1&#40; LPVOID input )
&#123;
    PMYPOS pData;
    pData = &#40;PMYPOS&#41;input;
    Sleep&#40;1000&#41;;
    printf&#40;"\n Creating 1... ");
    printf&#40;"Parameters = %d, %d\n",pData->alpha, pData->beta&#41;;

    return 0;
&#125;


DWORD WINAPI Thread_Init2&#40; LPVOID input )
&#123;
    PMYPOS pData;
    pData = &#40;PMYPOS&#41;input;
    Sleep&#40;100&#41;;
    printf&#40;"\n Creating 2... ");
    printf&#40;"Parameters = %d, %d\n",pData->alpha, pData->beta&#41;;

    return 0;
&#125;
Thread two prints to the screen before one! :D

Thanks for the help... there will inevitably be some more simple questions coming.

Regards

Richard
Richard Allbert
Posts: 792
Joined: Wed Jul 19, 2006 9:58 am

Re: SMP basics

Post by Richard Allbert »

Hi Gian-Carlo,

Simple question, simple solution!

Thanks for the reply... I was making it too complicated in my head.

Regards

Richard
Richard Allbert
Posts: 792
Joined: Wed Jul 19, 2006 9:58 am

Re: SMP basics

Post by Richard Allbert »

I see what you mean - therefore needing the

WaitForMultipleObjects()

function.

The problem I had was visualising the way the thread creation loop works.

Thanks

Richard