我知道主要发现得到了很好的研究,并且有很多不同的实现。我的问题是,使用提供的方法(代码示例),我该如何分解工作?它将运行的机器有4个四核超线程处理器和16GB内存。我意识到可以做出一些改进,特别是在IsPrime
方法中。我也知道,一旦列表中的项目超过int.MaxValue
,就会出现问题。我不关心任何这些改进。我唯一关心的是如何分解工作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Prime
{
class Program
{
static List<ulong> primes = new List<ulong>() { 2 };
static void Main(string[] args)
{
ulong reportValue = 10;
for (ulong possible = 3; possible <= ulong.MaxValue; possible += 2)
{
if (possible > reportValue)
{
Console.WriteLine(String.Format("\nThere are {0} primes less than {1}.", primes.Count, reportValue));
try
{
checked
{
reportValue *= 10;
}
}
catch (OverflowException)
{
reportValue = ulong.MaxValue;
}
}
if (IsPrime(possible))
{
primes.Add(possible);
Console.Write("\r" + possible);
}
}
Console.WriteLine(primes[primes.Count - 1]);
Console.ReadLine();
}
static bool IsPrime(ulong value)
{
foreach (ulong prime in primes)
{
if (value % prime == 0) return false;
if (prime * prime > value) break;
}
return true;
}
}
}
我看到有两种基本方案:1)使用所有线程来测试单个数字,这对于更高的素数可能很好,但我不能真正想到如何实现它,或者2)使用每个线程来测试单个可能的素数,当下一个要测试的数字大于找到的最高素数的平方时,可能导致找到非连续的素数串并遇到未使用的资源问题。
对我而言,感觉这两种情况只是在构建素数列表的早期阶段才具有挑战性,但我并不完全确定。这是为了打破这种工作的个人练习。
答案 0 :(得分:1)
如果需要,可以将两个操作并行化:检查素数,并立即检查多个素数。虽然我不确定这会有所帮助。说实话,我会考虑删除main()中的线程。
我试图保持对你的算法的忠诚,但是为了加快它的速度,我使用了x * x而不是reportvalue;如果你愿意,这是你可以轻易恢复的东西。
为了进一步改进我的核心拆分,您可以确定一种算法,根据数字的大小计算执行拆分所需的计算次数,并以此方式拆分列表。 (又名较小的数字需要较少的时间来划分,所以使第一个分区变大)
我的线程池概念可能不会以我想要的方式存在
这是我的去处(伪代码):
List<int> primes = {2};
List<int> nextPrimes = {};
int cores = 4;
main()
{
for (int x = 3; x < MAX; x=x*x){
int localmax = x*x;
for(int y = x; y < localmax; y+=2){
thread{primecheck(y);}
}
"wait for all threads to be executed"
primes.add(nextPrimes);
nextPrimes = {};
}
}
void primecheck(int y)
{
bool primality;
threadpool? pool;
for(int x = 0; x < cores; x++){
pool.add(thread{
if (!smallcheck(x*primes.length/cores,(x+1)*primes.length/cores ,y)){
primality = false;
pool.kill();
}
});
}
"wait for all threads to be executed or killed"
if (primality)
nextPrimes.add(y);
}
bool smallcheck(int a, int b, int y){
foreach (int div in primes[a to b])
if (y%div == 0)
return false;
return true;
}
E:我添加了我认为合并应该是什么样的内容,如果你想在没有它的情况下查看修订版。
答案 1 :(得分:0)
使用Eratosthenes的筛子代替。除非你首先使用一个好的算法,否则不值得并行化。
将空间分隔成大的区域,并在每个筛网中筛分。或者更好地为大区域使用一些工作区概念。
使用位数组来表示素数,它比显式表示它们所占用的空间更少。
另见this answer筛选的良好实施(在Java中,不分成区域)。