用于蒙特卡洛的 C# (.Net 4.5) 中的多线程
Multi-threading in C# (.Net 4.5) for monte-carlo
我的任务是采用蒙特卡洛模型并使用多线程使其 运行 更快。因为它是蒙特卡罗,每个模拟都独立于下一个。我想手动创建每个线程,因为每个线程都将进行 运行 数以千计的模拟并将每个模拟结果存储在数据库中,我想创建与处理器中的内核一样多的线程,并为它们提供高优先级。
这是用于管理这个的核心代码(我正在使用少量模拟进行测试):
var threads = new List<Thread>();
iNumCores = Environment.ProcessorCount;
iSims = 64;
iNumSimsPerThread = iSims / iNumCores;
for (int iThread = 0; iThread < iNumCores; iThread++)
{
iStart = (iThread * iNumSimsPerThread) + 1;
iEnd = ((iThread + 1) * iNumSimsPerThread);
Thread thread = new Thread(() => ProcessParallelMonteCarloTasks(iStart, iEnd, iSims));
thread.Priority = ThreadPriority.AboveNormal;
thread.Start();
threads.Add(thread);
}
foreach (var thread in threads)
thread.Join();
我的机器有 8 个内核,所以这个测试应该创建 8 个线程,每个线程 运行ning 8 次模拟。当我将结果数据写入数据库时,我包括了模拟编号。我希望看到 64 行,每次模拟 1 行。
但是,我每次模拟得到 1 行,最多 40 行,然后在 57 之前有一个间隙,然后 57 到 64 之间的每次模拟得到 3 行。
不幸的是,我无法调试线程,因此不知道发生了什么,也不知道为什么它缺少一些模拟和 运行ning 其他人的多个副本。当我打开任务管理器时,我可以看到程序 运行s.
时有 3-4 个核心未使用
有什么想法吗?
更新:
根据 Andre 的反馈,我查看了线程的调度和 'ProcessParallelMonteCarloTasks' 函数的执行。
我注意到的第一件事是某些线程连接到数据库时超时。我将最小池大小更改为等于核心数并解决了该问题,但这是创建线程的顺序并且 'ProcessParallelMonteCarloTasks' 得到 运行:
Execution order
在此实例中,模拟范围“17-24”、“41-48”和“57-64”被调用两次,而“1-8”、“25-32”和“49-56”被调用都不见了。
更新 2:
我一直在看我的任务管理器,因为这个 运行s 并将线程优先级设置为最高。我所看到的表明 运行3 个线程在 1 个核心上,2 个线程在 2 个核心上,1 个线程在第四个核心上。其他 4 个核心几乎处于闲置状态。有什么办法可以让每个核心 运行 1 个线程? 运行单核3个线程开销一定很大
iStart
和 iEnd
需要是新变量,我现在在你的循环中声明它们,否则(它们是免费的)你最终会捕获使用的变异值。
我的任务是采用蒙特卡洛模型并使用多线程使其 运行 更快。因为它是蒙特卡罗,每个模拟都独立于下一个。我想手动创建每个线程,因为每个线程都将进行 运行 数以千计的模拟并将每个模拟结果存储在数据库中,我想创建与处理器中的内核一样多的线程,并为它们提供高优先级。
这是用于管理这个的核心代码(我正在使用少量模拟进行测试):
var threads = new List<Thread>();
iNumCores = Environment.ProcessorCount;
iSims = 64;
iNumSimsPerThread = iSims / iNumCores;
for (int iThread = 0; iThread < iNumCores; iThread++)
{
iStart = (iThread * iNumSimsPerThread) + 1;
iEnd = ((iThread + 1) * iNumSimsPerThread);
Thread thread = new Thread(() => ProcessParallelMonteCarloTasks(iStart, iEnd, iSims));
thread.Priority = ThreadPriority.AboveNormal;
thread.Start();
threads.Add(thread);
}
foreach (var thread in threads)
thread.Join();
我的机器有 8 个内核,所以这个测试应该创建 8 个线程,每个线程 运行ning 8 次模拟。当我将结果数据写入数据库时,我包括了模拟编号。我希望看到 64 行,每次模拟 1 行。
但是,我每次模拟得到 1 行,最多 40 行,然后在 57 之前有一个间隙,然后 57 到 64 之间的每次模拟得到 3 行。
不幸的是,我无法调试线程,因此不知道发生了什么,也不知道为什么它缺少一些模拟和 运行ning 其他人的多个副本。当我打开任务管理器时,我可以看到程序 运行s.
时有 3-4 个核心未使用有什么想法吗?
更新: 根据 Andre 的反馈,我查看了线程的调度和 'ProcessParallelMonteCarloTasks' 函数的执行。
我注意到的第一件事是某些线程连接到数据库时超时。我将最小池大小更改为等于核心数并解决了该问题,但这是创建线程的顺序并且 'ProcessParallelMonteCarloTasks' 得到 运行:
Execution order
在此实例中,模拟范围“17-24”、“41-48”和“57-64”被调用两次,而“1-8”、“25-32”和“49-56”被调用都不见了。
更新 2: 我一直在看我的任务管理器,因为这个 运行s 并将线程优先级设置为最高。我所看到的表明 运行3 个线程在 1 个核心上,2 个线程在 2 个核心上,1 个线程在第四个核心上。其他 4 个核心几乎处于闲置状态。有什么办法可以让每个核心 运行 1 个线程? 运行单核3个线程开销一定很大
iStart
和 iEnd
需要是新变量,我现在在你的循环中声明它们,否则(它们是免费的)你最终会捕获使用的变异值。