【发布时间】:2017-02-14 04:39:15
【问题描述】:
我的代码中有一个 const LONGLONG UPPER = 1000000000;,我正在尝试计算从 1 到 UPPER 的所有数字的总和(是的,我知道有一个公式)。
这些是我的全局变量:
const LONGLONG UPPER = 1000000000;
const int NUM = 10; // number of threads
LONGLONG g_sum;
CRITICAL_SECTION cs_sum;
这是我的线程函数:
DWORD WINAPI SumThread(PVOID pvParam) {
LONGLONG i;
LONGLONG sum = 0;
LONGLONG x = (LONGLONG)pvParam;
x = x * (UPPER / NUM);
for (i = x + 1; i <= x + UPPER / NUM; i++) {
sum += i;
}
EnterCriticalSection(&cs_sum);
g_sum += sum;
LeaveCriticalSection(&cs_sum);
return 0;
}
这是我用来计算的代码:
HANDLE* hThreads = (HANDLE*)(malloc(sizeof(HANDLE) * NUM));
g_sum = 0;
InitializeCriticalSection(&cs_sum);
for (i = 0; i < NUM; i++) {
hThreads[i] = CreateThread(NULL, 0, SumThread, (PVOID)i, 0, NULL);
}
WaitForMultipleObjects(NUM, hThreads, TRUE, INFINITE);
DeleteCriticalSection(&cs_sum);
但是我得到了奇怪的结果:当我在一个简单的(串行)for 循环中对数字求和时,它的速度是多线程版本的两倍。当我将UPPER 乘以 10 并将线程数增加到 40 时,多线程版本甚至不会停止(大约 20 分钟后)。这是什么原因?
【问题讨论】:
-
如果只使用等于核心数或核心数减1的线程数会怎样?
-
我有 2 个物理处理器和 4 个逻辑处理器 - 我使用 2、3 和 4 个线程得到相同的结果。
-
有点相关,有很多更快的方法来计算顺序和。想一想:1 到 10。这与 (1+10) + (9+2) + (8+3) + (7+4) + (6+5) 相同。换句话说,它是 11 * 5 = 55。一次乘法而不是 9 次加法,最重要的是,没有循环。考虑如何将其应用于您的整体任务。
-
是的,正如我所说,我对公式很熟悉,但我将其作为练习。
-
在这种情况下,您在临界区中所做的事情非常简单,无需任何人也可以完成:请参阅 InterlockedAdd 函数。可能值得做出改变,看看它如何影响时间。
标签: c++ c windows multithreading winapi