如何修改一个for循环为Parallel.For? C#
How to modify a for cycle to Parallel.For? C#
我创建了一个非常简单的应用程序来计算 素数,然后将它们写下来。我想让它 运行 在所有核心上,如果用户选择计算例如 1 000 000
...
如何将我已经在运行的 for cycle 转换为所有内核上的 运行?
我发现有一个 Parallel.For
但我真的不知道如何从我现有的 for 循环转换成它...
{
bool isPrime = true;
int fPrime = Convert.ToInt32(txt_input.Text);
Application.DoEvents();
for (int i = 2; i <= fPrime; i++)
{
for (int j = 2; j <= fPrime; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
txt_result.Text = txt_result.Text + "..." + i;
}
isPrime = true;
}
txt_result.Text = txt_result.Text + Environment.NewLine + "Done";
}
更好的算法通常胜过更差(但并行化)的算法:
private static IEnumerable<int> Primes(int upTo) {
if (upTo <= 1)
yield break;
yield return 2; // Special case: the only even prime
List<int> primes = new List<int>() { };
for (int number = 3; number <= upTo; number += 2) {
int max = (int)(Math.Sqrt(number) + 0.5);
bool isPrime = true;
foreach (var div in primes)
if (div > max)
break;
else if (number % div == 0) {
isPrime = false;
break;
}
if (isPrime) {
primes.Add(number);
yield return number;
}
}
}
...
txt_result.Text = string.Join(", ", Primes(1000000));
你会得到
2, 3, 5, 7, 11, 13, 17, 19, 23, ... 999959, 999961, 999979, 999983
几分之一秒
您将无法使用并行 foreach 更新 UI,您可以编写一个方法来 return 所有素数
private static List<int> PrimeNumbers(int input)
{
var bag = new ConcurrentBag<int>();
Parallel.ForEach(Enumerable.Range(2, input), x =>
{
var isPrime = true;
Parallel.ForEach(Enumerable.Range(2, input), (y, state) =>
{
if ((x != y) && (x % y) == 0)
{
isPrime = false;
state.Break();
}
});
if (isPrime)
bag.Add(x);
});
return bag.AsEnumerable().OrderBy(x => x).ToList();
}
并行化外循环应该就足够了。您可能不会 运行 在处理器数量多于外部循环的机器中执行该程序!
Parallel.For(fromInclusive: 2, toExclusive: fPrime + 1, i =>
{
for (int j = 2; j <= fPrime; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
if (txt_result.InvokeRequired)
{
txt_result.Invoke((MethodInvoker)delegate { txt_result.Text = txt_result.Text + "..." + i; });
}
else
{
txt_result.Text = txt_result.Text + "..." + i;
}
}
isPrime = true;
});
txt_result.Text = txt_result.Text + Environment.NewLine + "Done";
我创建了一个非常简单的应用程序来计算 素数,然后将它们写下来。我想让它 运行 在所有核心上,如果用户选择计算例如 1 000 000
...
如何将我已经在运行的 for cycle 转换为所有内核上的 运行?
我发现有一个 Parallel.For
但我真的不知道如何从我现有的 for 循环转换成它...
{
bool isPrime = true;
int fPrime = Convert.ToInt32(txt_input.Text);
Application.DoEvents();
for (int i = 2; i <= fPrime; i++)
{
for (int j = 2; j <= fPrime; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
txt_result.Text = txt_result.Text + "..." + i;
}
isPrime = true;
}
txt_result.Text = txt_result.Text + Environment.NewLine + "Done";
}
更好的算法通常胜过更差(但并行化)的算法:
private static IEnumerable<int> Primes(int upTo) {
if (upTo <= 1)
yield break;
yield return 2; // Special case: the only even prime
List<int> primes = new List<int>() { };
for (int number = 3; number <= upTo; number += 2) {
int max = (int)(Math.Sqrt(number) + 0.5);
bool isPrime = true;
foreach (var div in primes)
if (div > max)
break;
else if (number % div == 0) {
isPrime = false;
break;
}
if (isPrime) {
primes.Add(number);
yield return number;
}
}
}
...
txt_result.Text = string.Join(", ", Primes(1000000));
你会得到
2, 3, 5, 7, 11, 13, 17, 19, 23, ... 999959, 999961, 999979, 999983
几分之一秒
您将无法使用并行 foreach 更新 UI,您可以编写一个方法来 return 所有素数
private static List<int> PrimeNumbers(int input)
{
var bag = new ConcurrentBag<int>();
Parallel.ForEach(Enumerable.Range(2, input), x =>
{
var isPrime = true;
Parallel.ForEach(Enumerable.Range(2, input), (y, state) =>
{
if ((x != y) && (x % y) == 0)
{
isPrime = false;
state.Break();
}
});
if (isPrime)
bag.Add(x);
});
return bag.AsEnumerable().OrderBy(x => x).ToList();
}
并行化外循环应该就足够了。您可能不会 运行 在处理器数量多于外部循环的机器中执行该程序!
Parallel.For(fromInclusive: 2, toExclusive: fPrime + 1, i =>
{
for (int j = 2; j <= fPrime; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
if (txt_result.InvokeRequired)
{
txt_result.Invoke((MethodInvoker)delegate { txt_result.Text = txt_result.Text + "..." + i; });
}
else
{
txt_result.Text = txt_result.Text + "..." + i;
}
}
isPrime = true;
});
txt_result.Text = txt_result.Text + Environment.NewLine + "Done";