多线程-计算1到5万的乘积
本帖最后由 wang2006zhi 于 2025-2-14 12:16 编辑int start = 1;
int end = 50000;
#region 线程实现
var sw1 = new Stopwatch();
sw1.Start();
int mid = (start + end) / 3;
// 使用三个任务分别计算前中后部分的乘积;
// 测试中当任务开到6个时候,用时550,效率提升不明显,说明任务也是有时间消耗,得综合考虑。
Task<BigInteger> task1 = Task.Run(() => Calculate(start, mid));
Task<BigInteger> task2 = Task.Run(() => Calculate(mid + 1, 2*mid));
Task<BigInteger> task3 = Task.Run(() => Calculate(2*mid + 1, end));
// 等待三个任务完成
Task.WaitAll(task1, task2, task3);
// 计算最终乘积
BigInteger result1 = task1.Result * task2.Result* task3.Result;
sw1.Stop();
#endregion
#region 常规实现
var sw2 = new Stopwatch();
sw2.Start();
//以下测试用时1200左右
var result2=Calculate(start, end);
//以下测试用时700左右
//var r1=Calculate(start, mid);
//var r2=Calculate(mid + 1, 2*mid);
//var r3=Calculate(2 * mid + 1, end);
//var result2 = r1 * r2 * r3;
sw2.Stop();
#endregion
Env.Editor.WriteMessage($"\n 计算结果相等?{result1==result2}" +
$"\n 线程/常规(毫秒):{sw1.ElapsedMilliseconds}/{sw2.ElapsedMilliseconds}");
static BigInteger Calculate(int start, int end)
{
BigInteger product = 1;
for (int i = start; i <= end; i++)
{
product *= i;
}
return product;
}
建议开核心数/2 的任务数量,你这个3个任务可能你cpu是6核的.可以通过获取cpu核心数Environment.ProcessorCount/2动态创建任务数量 本帖最后由 moy838840554 于 2024-8-28 10:55 编辑
当然,这个代码在你的电脑上跑效果可能没差别,得换到cpu核心数更多的电脑上跑
int start = 1;
int end = 50000;
int processorCount = Environment.ProcessorCount/2; // 获取 CPU 核心数/2
int range =end / processorCount; // 计算每个线程的范围
#region 线程实现
var sw1 = new Stopwatch();
sw1.Start();
Task<BigInteger>[] tasks = new Task<BigInteger>;
for (int i = 0; i < processorCount; i++)
{
int taskStart = start + i * range;
int taskEnd = (i == processorCount - 1) ? end : taskStart + range - 1; // 确保最后一个任务处理到结束
tasks = Task.Run(() => Calculate(taskStart, taskEnd));
}
// 等待所有任务完成
Task.WaitAll(tasks);
// 计算最终乘积
BigInteger result1 = 1;
foreach (var task in tasks)
{
result1 *= task.Result;
}
sw1.Stop();
#endregion
#region 常规实现
var sw2 = new Stopwatch();
sw2.Start();
var result2 = Calculate(start, end);
sw2.Stop();
#endregion
Env.Editor.WriteMessage($"\n 计算结果相等?{result1 == result2}" +
$"\n 线程/常规(毫秒):{sw1.ElapsedMilliseconds}/{sw2.ElapsedMilliseconds}");
本帖最后由 wang2006zhi 于 2024-8-28 12:05 编辑
moy838840554 发表于 2024-8-28 10:53
当然,这个代码在你的电脑上跑效果可能没差别,得换到cpu核心数更多的电脑上跑经过实测。。可能数据量还不够大,体现不了线程优势。。。另外实测,常规计算中也可以拆分10分部计算在合并计算,时间差不多
命令: TT1
计算结果相等?True,核心数20
线程/常规(毫秒):552/1118
命令: TT1
计算结果相等?True,核心数20
线程/常规(毫秒):564/1110
命令: TT1
计算结果相等?True,核心数20
线程/常规(毫秒):724/1123
命令: TT1
计算结果相等?True,核心数20 本帖最后由 你有种再说一遍 于 2024-8-28 19:30 编辑
wang2006zhi 发表于 2024-8-28 12:03
经过实测。。可能数据量还不够大,体现不了线程优势。。。另外实测,常规计算中也可以拆分10分部计算在合并 ...
1,你没有用Parallel.For
2,你没学循环展开,不知道CPU分支流水线技术.
3,一定要具体任务具体学习.你采用bigint了,它不是基础的数值类型,它还是不定长内存,除非你做银行业务,不然用这个干什么...光学新建几个线程本身是不行的,还要结合使用SIMD等等.
页:
[1]