【发布时间】:2014-07-27 12:11:16
【问题描述】:
这可能并不奇怪,只是我似乎无法解释。我只是对并行编程进行了一些试验,我想我会实现可以并行的最直接的例子;计算素数。
问题是:我似乎无法让 4 个逻辑处理器比单线程计算更快。这是为什么? (我有一个 i7-4500u)
这是我的代码(您基本上可以将其粘贴到新的控制台应用程序中):
static void Main(string[] args)
{
var p = new Program();
p.Start();
}
private void Start()
{
StartMonitoringTask();
// This puts my cpu at 33%, but is really fast.
for (long current = 3; current < long.MaxValue; current++)
{
DeterminePrimeAndAddToTotal(current);
}
// This puts my cpu at 100%, but is way slower.
Parallel.For(3, long.MaxValue, (current) => DeterminePrimeAndAddToTotal(current));
}
private long lastPrime = 0;
private long totalFound = 0;
private void DeterminePrimeAndAddToTotal(long primeOrNot)
{
bool isPrime = true;
if (primeOrNot % 2 == 0) return; // even number? never prime.
long root = (long)Math.Sqrt((long)primeOrNot);
for (int i = 3; i <= root; i += 2) // check only uneven numbers.
{
if (primeOrNot % i == 0)
{
isPrime = false;
break;
}
}
if(isPrime)
{
totalFound++;
lastPrime = primeOrNot;
}
}
/// <summary>
/// This just starts a task to monitor the progress.
/// It's outputs the results to the console every second or so.
/// </summary>
private void StartMonitoringTask()
{
Task.Factory.StartNew(() =>
{
var sw = Stopwatch.StartNew();
while (true)
{
Task.Delay(1000).Wait();
Console.WriteLine(
"found: " + totalFound +
", last: " + lastPrime +
", " + (totalFound / (sw.ElapsedMilliseconds / 1000)) + " p/s");
}
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
更新(基于弗罗德的回答): Frode 的回答似乎是合理的,所以为了证明这一点,我在 for 和并行循环之外添加了 Parallel.Invoke 的一些操作。像这样:
var numberOfActions = 20;
var actions = new List<Action>();
long chunkSize = int.MaxValue / numberOfActions;
for (int i = 0; i < numberOfActions; i++)
{
long from, to;
from = i == 0 ? 3 : (i * chunkSize);
to = (i + 1) * chunkSize;
actions.Add(new Action(() => { for (long j = from; j < to; j++) DeterminePrimeAndAddToTotal(j); }));
}
Parallel.Invoke(actions.ToArray());
这似乎和 Parallel.For 一样慢。我错过了什么?
【问题讨论】:
-
你怎么知道它更慢...你这里有一个竞争条件,这很容易“降低”结果。
-
@ShlomiBorovitz 我要么评论 for 循环,要么评论并行循环。我在这里没有评论它们。除此之外,两个循环的条件是相同的。
-
你的意思是注释掉......无论如何,这与竞争条件问题无关。
-
@ShlomiBorovitz 怎么样?如果你运行代码,你会得到什么结果?
-
我正在寻找答案。在那之前,你不能指望竞争条件是确定性的 - 所以......回答这个问题有什么意义?
标签: c# parallel-processing task-parallel-library primes