0

Is there a thread limit EnterCriticalSection() can cope with? The following code works fine with 64 threads, but it crashes when using 65 or more:

CRITICAL_SECTION TestCritSection;

unsigned int threadId;

int getThreadId()
{
    int tid = -1;

    EnterCriticalSection(&TestCritSection);

    tid= threadId;
    threadId++;

    LeaveCriticalSection(&TestCritSection);

    return tid;
}

void parallelTest()
{
    int tid = getThreadId();
    cout << "Thread " << tid << " executed" << endl;
}


void
multiThreadTest()
{
    unsigned int numThreads = 64; // fine, but program crashes when numThreads is set to 65 or more
    HANDLE *threads = new HANDLE[numThreads];
    DWORD ThreadID;
    threadId = 1;

    if (!InitializeCriticalSectionAndSpinCount(&TestCritSection, 0x00000400)) return;

    for (int i=0; i<numThreads; ++i)
    {
        threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) parallelTest, (LPVOID) NULL, 0, &ThreadID);
    }

    WaitForMultipleObjects(numThreads, threads, TRUE, INFINITE);

    DeleteCriticalSection(&TestCritSection);

    for (int i=0; i<numThreads; ++i)
    {
        CloseHandle(threads[i]);
    }

    delete [] threads;
}

I guess CRITICAL_SECTION is internally using a semaphore with a max count of 64. Can I somehow change that?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Ben
  • 4,486
  • 6
  • 33
  • 48
  • 7
    The problem is WaitForMultipleObjects, not the critical section. *Never* ignore an api function return value. – Hans Passant Jun 22 '12 at 16:42
  • 1
    Reading material: http://msdn.microsoft.com/en-us/magazine/cc164040.aspx – Steve-o Jun 22 '12 at 16:47
  • Oh... that did not come to my mind. So the limit is MAXIMUM_WAIT_OBJECTS... – Ben Jun 22 '12 at 16:50
  • I also feel obliged to point out that having more threads than virtual cores isn't likely to improve performance (and may hurt performance) - at the end of the day, the system can only do one thing at a time. – Larry Osterman Jun 23 '12 at 14:51
  • @LarryOsterman: What about performance tests? I'm doing a benchmark test on a MySQL cluster with 5 nodes. The threads are basically all waiting for results from the database. I can easily fire 64 threads on one db machine with increased performance compared to 48. So why not try more? – Ben Jun 25 '12 at 08:23
  • If you're app spends all its time blocked on I/O, then yeah, more threads can help - to a limit. At some point the overhead of managing all the threads overwhelms the benefit of mulitple threads. It might be interesting to investigate the benefits of using async I/O and thus freeing the I/O threads to do more useful work. – Larry Osterman Jun 25 '12 at 13:27

1 Answers1

1

As nobody wants to answer my question, I will do it myself based on HansPassant's comment to my question.

He pointed out that the problem is WaitForMultipleObjects(), which takes a parameter

nCount [in]

The number of object handles in the array pointed to by lpHandles.

The maximum number of object handles is MAXIMUM_WAIT_OBJECTS. This parameter cannot be zero.

(from msdn)

MAXIMUM_WAIT_OBJECTS is defined as 64, more informations in this thread.

This means: yes, there is a hard-coded limit on the amount of threads, but the restriction is not on EnterCriticalSection but on WaitForMultipleObjects, which returns an error code I should have checked.

Here is more information on how to get more than 64 threads working in parallel.

Community
  • 1
  • 1
Ben
  • 4,486
  • 6
  • 33
  • 48