Welcome to Dream.In.Code
Getting C++ Help is Easy!

Join 105,776 C++ Programmers for FREE! Ask your question and get quick answers from experts. There are 1,257 online right now! We've got more than 500 tutorials and 2,000 snippets. Join and find out why Dream.In.Code is the #1 programming help community on the internet! Registration is fast and FREE... Join Now!



Multi-threading on Multi-processors

 
Reply to this topicStart new topic

> Multi-threading on Multi-processors, creating a thread for each processor

Rating  5
bizzehdee
Group Icon



post 17 May, 2008 - 03:01 PM
Post #1


this piece of code was writen to do a large amount of data processing, and i wanted to take full advantage of multi-core/multi-processor machines as much as possible.

first, you need to know how many processors/cores are available to you.

this is done with the GetNumCPUs() function.
CODE
DWORD_PTR GetNumCPUs() {
  SYSTEM_INFO m_si = {0, };
  GetSystemInfo(&m_si);
  return (DWORD_PTR)m_si.dwNumberOfProcessors;
}

this pretty much returns the number of available cores (note: single cpu's that are hyperthreading enabled also show as 2 cpu's).

once you have the number of processor, you can then create a loop that will cycle through each processor.
CODE
DWORD_PTR c = GetNumCPUs();
for(DWORD_PTR i = 0; i < c; i++) {

}


this will simply cycle through a for loop at least once (because you will always have 1 processor) upto the number of processors/cores you have.

now, if you want to actualy DO something with this loop and your processors/cores, you will need to create some threads for them. each thread will run independantly of the others within the application (though, they can interact, this is not the purpous of this tutorial).

first you will need to create your thread procedure.
CODE
DWORD_PTR WINAPI threadMain(void* p) {

  return 0;
}


this is a simple "do nothing" thread that you can fill in later.

next, you will need to create the threads.
CODE
m_threads = new HANDLE[c]; //needed to store the handles of your threads
DWORD_PTR c = GetNumCPUs();
for(DWORD_PTR i = 0; i < c; i++) {
  DWORD_PTR m_id = 0; //mostly useless, just to complete the CreateThread function

  //create the thread and store its handle for later, and pass the processor count to the thread
  m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain, (LPVOID)i, NULL, &m_id);
}


now you have a thread running for each cpu within the current system (ie, on mine it would be 2, on a quad core, it would be 4, on a single core system, it would be 1), but we havnt assigned them to any particular cpu or core yet. the processor its self, and the operating system will generaly do this for you automaticaly, but wont split them up equaly, they will just offload them to the processors/cores that are least being utalized at the time.

so now, we will assign the threads to each processor/core our selfs.
CODE
m_threads = new HANDLE[c]; //needed to store the handles of your threads
DWORD_PTR c = GetNumCPUs();
for(DWORD_PTR i = 0; i < c; i++) {
  DWORD_PTR m_id = 0; //mostly useless, just to complete the CreateThread function
  DWORD_PTR m_mask = 1 << i; //creates a mask of the processor/core number

  //create the thread and store its handle for later, and pass the processor count to the thread
  m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain, (LPVOID)i, NULL, &m_id);
  SetThreadAffinityMask(m_threads[i], m_mask); //assigns the thread to a processor/core

  wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask); //just so we can see whats going on as it goes on (if your not using unicode, you should use printf here and not wprintf.
}


and thats it, put it together, and you have an application that can be far more effective at doing almost anything as long as you know what your doing.

CODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

HANDLE *m_threads = NULL;
DWORD_PTR WINAPI threadMain(void* p);

DWORD_PTR GetNumCPUs() {
  SYSTEM_INFO m_si = {0, };
  GetSystemInfo(&m_si);
  return (DWORD_PTR)m_si.dwNumberOfProcessors;
}

int wmain(int argc, wchar_t **args) {
  DWORD_PTR c = GetNumCPUs();

  m_threads = new HANDLE[c];

  for(DWORD_PTR i = 0; i < c; i++) {
    DWORD_PTR m_id = 0;
    DWORD_PTR m_mask = 1 << i;

    m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain, (LPVOID)i, NULL, &m_id);
    SetThreadAffinityMask(m_threads[i], m_mask);

    wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask);
  }

  return 0;
}

DWORD_PTR WINAPI threadMain(void* p) {

  return 0;
}


Research: CreateThread | SetThreadAffinityMask | GetSystemInfo
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!


Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 8/21/08 04:18PM

Live C++ Help!

C++ Tutorials

Reference Sheets

C++ Snippets

Bye Bye Ads

Free DIC T-Shirt

T-Shirt Example

Related Sites

Monthly Drawing

Thumb Drive

Partners

Top Contributors

Top 10 Kudos This Month