在大量线程上运行程序时结果突然出错; WaitForMultipleObjects 结束后调用线程

问题描述 投票:0回答:1

我有一个任务,将一个简单的加法周期(基本上是 i++ 100000000 次)分成多个线程,并对它们进行计时,以查看性能如何变化。当线程数低于 100 时,我的代码工作正常,但在 100 个线程之后,它开始产生完全虚假的结果。我尝试打印每个线程的输出来查明问题所在,大多数都返回0。然后我给每个线程添加了一个id参数,以便它们在调用时打印,结果发现一旦有超过100个线程有些根本没有被调用,有些被调用 after WaitForMultipleObjects 应该捕获它们。我的猜测是它超时了,但它设置为无限。

这是代码:

#include <windows.h>
#include <iostream> 
using namespace std;
#include <stdio.h>
#include <cmath>

DWORD WINAPI fun(LPVOID lpParam);
typedef struct segm {
    int start;
    int stop;
    double res;
    int id;
}*PSEGM;

DWORD   thrID[500];
HANDLE  handles[500];
int m = 100000000;
int n;
double res;

int ns[25] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
              16,20,30,40,50,100,200,300,400,500 };

DWORD WINAPI fun(LPVOID lpParam) {
    PSEGM ps;
    ps = (PSEGM)lpParam;
    printf("%d ", ps->id);
    for (int i = ps->start; i < ps->stop; i++) {
        ps->res += 1;
    }
    return 0;
}

struct segm sa[500];
int main()
{
    for (int i = 0; i < 25; i++) {
        n = ns[i];
        int step = m / n;
        res = 0;
        printf("\n\ni=%d; n=%d;", i,n);
        for (int k = 0; k < n; k++) {
            sa[k].start = k * step + 1;
            sa[k].stop = (k + 1) * step;
            sa[k].res = 0;
            sa[k].id = k; 
        }
        sa[0].start = 0;
        sa[n - 1].stop = m;
       
        for (int k = 0; k < n; k++) {
            handles[k] = CreateThread(NULL,0,fun, &sa[k],0,&thrID[k]);
            if (handles[k] == NULL){ ExitProcess(3);}
        }
        WaitForMultipleObjects(n, handles, TRUE, INFINITE);
        for (int k = 0; k < n; k++){
            res += sa[k].res;
            CloseHandle(handles[k]);
            //printf("%d:%2.4f ", k, sa[k].res);
        }
        printf("total: ");
        cout << res;

    }    
}

正常输出和虚假输出的示例(为了简洁起见,我从示例中删除了计时内容):

i=19; n=50;0 1 2 3 6 5 8 4 7 12 16 14 20 18 25 26 9 10 11 13 15 17 34 19 36 22 23 38 27 40 41 42 43 44 33 35 45 37 24 47 28 48 30 31 49 32 21 46 39 29 time: 0.0410; total: 1e+08

i=20; n=100;0 3 4 1 5 6 7 9 2 8 10 13 12 20 14 15 11 18 21 16 17 37 19 41 22 23 24 25 26 27 28 29 30 34 35 39 74 75 time: 0.0280; total: 3.4e+0731 40 32 76 33 42 46 47 48 49 98 84 43 53 54 55 56 58 57 59

我还收到这两个警告:

Using uninitialized memory 'handles[BYTE:0]' 
Buffer overrun while writing to 'sa'
。我不明白怎么会出现缓冲区溢出;我尝试将 sa 变大,但警告并没有消失。我想我也已经初始化了一切。不过,我不知道这些事情是否与错误有关。

我真的很困惑和困惑,希望得到任何帮助。谢谢!

c++ multithreading winapi
1个回答
2
投票

WaitForMultipleObjects
最多只能等待
MAXIMUM_WAIT_OBJECTS
(即 64 个)句柄。一旦您尝试等待更多句柄(代码中就是这种情况),等待就会失败,因此您的输出是垃圾。

如果您想等待超过 MAXIMUM_WAIT_OBJECTS 个句柄,则需要采取其他措施。

像这样更改你的代码,运行它,你会看到会发生什么:

    auto r = WaitForMultipleObjects(n, handles, TRUE, INFINITE);
    if (r != 0)
      printf("WaitForMultipleObjects failed, last error = %d\N", GetLastError());
© www.soinside.com 2019 - 2024. All rights reserved.