我有一个任务,将一个简单的加法周期(基本上是 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 变大,但警告并没有消失。我想我也已经初始化了一切。不过,我不知道这些事情是否与错误有关。
我真的很困惑和困惑,希望得到任何帮助。谢谢!
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());