明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 706|回复: 4

[其它] 多线程初体验-计算1到5万的乘积

[复制链接]
发表于 2024-8-28 00:06:23 | 显示全部楼层 |阅读模式
本帖最后由 wang2006zhi 于 2024-8-28 10:12 编辑

int start = 1;
int end = 50000;
#region 线程实现
var sw1 = new Stopwatch();
sw1.Start();
int mid = (start + end) / 3;
// 使用三个任务分别计算前中后部分的乘积;

// 测试中当任务开到6个时候,用时550,效率提升不明显,说明任务也是有时间消耗,得综合考虑。
Task<BigInteger> task1 = Task.R
un(() => 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;
}






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2024-8-28 10:49:23 | 显示全部楼层
建议开核心数/2 的任务数量,你这个3个任务可能你cpu是6核的.可以通过获取cpu核心数Environment.ProcessorCount/2动态创建任务数量
发表于 2024-8-28 10:53:25 | 显示全部楼层
本帖最后由 moy838840554 于 2024-8-28 10:55 编辑


当然,这个代码在你的电脑上跑效果可能没差别,得换到cpu核心数更多的电脑上跑
  1.   int start = 1;
  2.         int end = 50000;
  3.         int processorCount = Environment.ProcessorCount/2; // 获取 CPU 核心数/2
  4.         int range =end / processorCount; // 计算每个线程的范围

  5.         #region 线程实现
  6.         var sw1 = new Stopwatch();
  7.         sw1.Start();

  8.         Task<BigInteger>[] tasks = new Task<BigInteger>[processorCount];

  9.         for (int i = 0; i < processorCount; i++)
  10.         {
  11.             int taskStart = start + i * range;
  12.             int taskEnd = (i == processorCount - 1) ? end : taskStart + range - 1; // 确保最后一个任务处理到结束

  13.             tasks = Task.Run(() => Calculate(taskStart, taskEnd));
  14.         }

  15.         // 等待所有任务完成
  16.         Task.WaitAll(tasks);

  17.         // 计算最终乘积
  18.         BigInteger result1 = 1;
  19.         foreach (var task in tasks)
  20.         {
  21.             result1 *= task.Result;
  22.         }

  23.         sw1.Stop();
  24.     #endregion

  25.     #region 常规实现
  26.     var sw2 = new Stopwatch();
  27.     sw2.Start();

  28.     var result2 = Calculate(start, end);

  29.     sw2.Stop();
  30. #endregion

  31. Env.Editor.WriteMessage($"\n 计算结果相等?{result1 == result2}" +
  32.         $"\n 线程/常规(毫秒):{sw1.ElapsedMilliseconds}/{sw2.ElapsedMilliseconds}");

 楼主| 发表于 2024-8-28 12:03:26 | 显示全部楼层
本帖最后由 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 15:24:39 | 显示全部楼层
本帖最后由 你有种再说一遍 于 2024-8-28 19:30 编辑
wang2006zhi 发表于 2024-8-28 12:03
经过实测。。可能数据量还不够大,体现不了线程优势。。。另外实测,常规计算中也可以拆分10分部计算在合并 ...


1,你没有用Parallel.For
2,你没学循环展开,不知道CPU分支流水线技术.
3,一定要具体任务具体学习.你采用bigint了,它不是基础的数值类型,它还是不定长内存,除非你做银行业务,不然用这个干什么...光学新建几个线程本身是不行的,还要结合使用SIMD等等.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-22 18:57 , Processed in 0.185141 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表