C#埃拉托什尼误解
我有两个用Eratosthenes筛生成素数的函数,一个使用简单循环,另一个使用任务在多个线程上运行计算 由于在使用线程时需要锁定值列表,所以我假设线程版本不会比正常版本快。但是经过一些测试,普通版本似乎比线程版本差6倍左右 更奇怪的是,当一次只使用一个任务时,它比普通版本快6倍。 我错过了什么 代码如下:C#埃拉托什尼误解,c#,multithreading,primes,C#,Multithreading,Primes,我有两个用Eratosthenes筛生成素数的函数,一个使用简单循环,另一个使用任务在多个线程上运行计算 由于在使用线程时需要锁定值列表,所以我假设线程版本不会比正常版本快。但是经过一些测试,普通版本似乎比线程版本差6倍左右 更奇怪的是,当一次只使用一个任务时,它比普通版本快6倍。 我错过了什么 代码如下: 公共静态列表UsualPrimesGenerator(int n) { if(n
公共静态列表UsualPrimesGenerator(int n)
{
if(n<0)
返回新列表();
List res=新列表();
对于(int i=2;ip!=i2&&p%i2==0);
}
});
}
}
对于(int i=0;i
n=100000的时间测试结果:
Usual Prime Generator: 2732ms
9592 Primes found
Magic Prime Generator: 397ms
9592 Primes found
存在差异的原因是,在简单的解决方案中要进行更多的迭代。如果将循环更改为:
for (int i = 2; i * 2 <= n; i++)
{
res.RemoveAll(p => p != i && p % i == 0);
}
我没有检查正确性,但我想这不是你的问题。
此外,您的测量方法可以改进,如上所述。但这不是本案的问题所在
循环中带有计数器的完整代码
class Program
{
private const int n = 100000;
static void Main(string[] args)
{
MagicPrimesGenerator(n, 12);
MagicPrimesGenerator(n, 12);
MagicPrimesGenerator(n, 12);
MagicPrimesGenerator(n, 12);
UsualPrimesGenerator(n);
UsualPrimesGenerator(n);
UsualPrimesGenerator(n);
UsualPrimesGenerator(n);
var sw = new Stopwatch();
sw.Start();
sw.Reset();
sw.Start();
MagicPrimesGenerator(n, 1);
Console.WriteLine($"B: Magic Prime Generator: {sw.ElapsedMilliseconds} ms");
sw.Reset();
sw.Start();
UsualPrimesGenerator(n);
Console.WriteLine($"A: Usual Prime Generator: {sw.ElapsedMilliseconds} ms");
}
public static List<int> UsualPrimesGenerator(int n)
{
int count = 0;
if (n < 0)
return new List<int>();
List<int> res = new List<int>();
for (int i = 2; i < n; i++) res.Add(i);
for (int i = 2; i * 2 <= res.Count; i++)
{
res.RemoveAll(p => p != i && p % i == 0);
count++;
}
Console.Write("usual iteration count ");
Console.WriteLine(count);
return res;
}
public static List<int> MagicPrimesGenerator(int n, int nbTasks)
{
if (nbTasks <= 0)
throw new ArgumentException("Nbthread must be positive");
var threads = new Task[nbTasks];
int count = 0;
List<int> primes = new List<int>();
for (int i = 2; i <= n; i++)
primes.Add(i);
for (int i = 2; i * 2 <= primes.Count; i++)
{
if (threads[i % nbTasks] == null)
{
var i2 = i;
threads[i % nbTasks] = Task.Run(() =>
{
lock (primes)
{
primes.RemoveAll(p => p != i2 && p % i2 == 0);
count++;
}
});
}
else
{
threads[i % nbTasks].Wait();
var i2 = i;
threads[i % nbTasks] = Task.Run(() =>
{
lock (primes)
{
primes.RemoveAll(p => p != i2 && p % i2 == 0);
count++;
}
});
}
}
for (int i = 0; i < nbTasks; i++)
{
if (threads[i] != null)
threads[i].Wait();
}
Console.Write("magic iteration count ");
Console.WriteLine(count);
return primes;
}
}
类程序
{
私人建筑单位n=100000;
静态void Main(字符串[]参数)
{
magicpromesgenerator(n,12);
magicpromesgenerator(n,12);
magicpromesgenerator(n,12);
magicpromesgenerator(n,12);
通常情况下,发电机(n);
通常情况下,发电机(n);
通常情况下,发电机(n);
通常情况下,发电机(n);
var sw=新秒表();
sw.Start();
sw.Reset();
sw.Start();
magicpromesgenerator(n,1);
Console.WriteLine($“B:Magic Prime Generator:{sw.elapsedmillesons}ms”);
sw.Reset();
sw.Start();
通常情况下,发电机(n);
WriteLine($“A:常用的素数生成器:{sw.elapsedmillesons}ms”);
}
公共静态列表UsualPrimesGenerator(int n)
{
整数计数=0;
if(n<0)
返回新列表();
List res=新列表();
对于(int i=2;ip!=i2&&p%i2==0);
计数++;
}
});
}
}
对于(int i=0;i
之所以存在差异,是因为您在简单的解决方案中进行了更多的迭代。如果将循环更改为:
for (int i = 2; i * 2 <= n; i++)
{
res.RemoveAll(p => p != i && p % i == 0);
}
我没有检查正确性,但我想这不是你的问题。
此外,您的测量方法可以改进,如上所述。但这不是本案的问题所在
循环中带有计数器的完整代码
class Program
{
private const int n = 100000;
static void Main(string[] args)
{
MagicPrimesGenerator(n, 12);
MagicPrimesGenerator(n, 12);
MagicPrimesGenerator(n, 12);
MagicPrimesGenerator(n, 12);
UsualPrimesGenerator(n);
UsualPrimesGenerator(n);
UsualPrimesGenerator(n);
UsualPrimesGenerator(n);
var sw = new Stopwatch();
sw.Start();
sw.Reset();
sw.Start();
MagicPrimesGenerator(n, 1);
Console.WriteLine($"B: Magic Prime Generator: {sw.ElapsedMilliseconds} ms");
sw.Reset();
sw.Start();
UsualPrimesGenerator(n);
Console.WriteLine($"A: Usual Prime Generator: {sw.ElapsedMilliseconds} ms");
}
public static List<int> UsualPrimesGenerator(int n)
{
int count = 0;
if (n < 0)
return new List<int>();
List<int> res = new List<int>();
for (int i = 2; i < n; i++) res.Add(i);
for (int i = 2; i * 2 <= res.Count; i++)
{
res.RemoveAll(p => p != i && p % i == 0);
count++;
}
Console.Write("usual iteration count ");
Console.WriteLine(count);
return res;
}
public static List<int> MagicPrimesGenerator(int n, int nbTasks)
{
if (nbTasks <= 0)
throw new ArgumentException("Nbthread must be positive");
var threads = new Task[nbTasks];
int count = 0;
List<int> primes = new List<int>();
for (int i = 2; i <= n; i++)
primes.Add(i);
for (int i = 2; i * 2 <= primes.Count; i++)
{
if (threads[i % nbTasks] == null)
{
var i2 = i;
threads[i % nbTasks] = Task.Run(() =>
{
lock (primes)
{
primes.RemoveAll(p => p != i2 && p % i2 == 0);
count++;
}
});
}
else
{
threads[i % nbTasks].Wait();
var i2 = i;
threads[i % nbTasks] = Task.Run(() =>
{
lock (primes)
{
primes.RemoveAll(p => p != i2 && p % i2 == 0);
count++;
}
});
}
}
for (int i = 0; i < nbTasks; i++)
{
if (threads[i] != null)
threads[i].Wait();
}
Console.Write("magic iteration count ");
Console.WriteLine(count);
return primes;
}
}
类程序
{
私人建筑单位n=100000;
静态void Main(字符串[]参数)
{
magicpromesgenerator(n,12);
magicpromesgenerator(n,12);
magicpromesgenerator(n,12);
magicpromesgenerator(n,12);
通常情况下,发电机(n);
通常情况下,发电机(n);
通常情况下,发电机(n);
通常情况下,发电机(n);
var sw=新秒表();
sw.Start();
sw.Reset();
sw.Start();
magicpromesgenerator(n,1);
Console.WriteLine($“B:Magic Prime Generator:{sw.elapsedmillesons}ms”);
sw.Reset();
sw.Start();
通常情况下,发电机(n);
WriteLine($“A:常用的素数生成器:{sw.elapsedmillesons}ms”);
}
公共静态列表UsualPrimesGenerator(int n)
{
整数计数=0;
if(n<0)
返回新列表();
List res=新列表();
对于(int i=2;ip!=i2&&p%i2==0);
计数++;
}
});
}
}
对于(int i=0;i
这些不是线程
。这些是任务
。线程和任务。是的,对不起,错了,我知道