C# 关于多线程和CPU的问题

使用1个线程进行操作耗时100秒

为什么使用2个线程和使用20个线程都一样只节省一半时间

照理说20个线程不是应该更省时间吗? 求解...

1.CPU发展趋势
核心数目依旧会越来越多,依据摩尔定律,由于单个核心性能提升有着严重的瓶颈问题,普通的桌面PC有望在2017年末2018年初达到24核心(或者16核32线程),我们如何来面对这突如其来的核心数目的增加?编程也要与时俱进。笔者斗胆预测,CPU各个核心之间的片内总线将会采用4路组相连:),因为全相连太过复杂,单总线又不够给力。而且应该是非对称多核处理器,可能其中会混杂几个DSP处理器或流处理器。

2.多线程与并行计算的区别
(1)多线程的作用不只是用作并行计算,他还有很多很有益的作用。
还在单核时代,多线程就有很广泛的应用,这时候多线程大多用于降低阻塞(意思是类似于
while(1)
{
if(flag==1)
break;
sleep(1);
}
这样的代码)带来的CPU资源闲置,注意这里没有浪费CPU资源,去掉sleep(1)就是纯浪费了。
阻塞在什么时候发生呢?一般是等待IO操作(磁盘,数据库,网络等等)。此时如果单线程,CPU会干转不干实事(与本程序无关的事情都算不干实事,因为执行其他程序对我来说没意义),效率低下(针对这个程序而言),例如一个IO操作要耗时10毫秒,CPU就会被阻塞接近10毫秒,这是何等的浪费啊!要知道CPU是数着纳秒过日子的。
所以这种耗时的IO操作就用一个线程Thread去代为执行,创建这个线程的函数(代码)部分不会被IO操作阻塞,继续干这个程序中其他的事情,而不是干等待(或者去执行其他程序)。

同样在这个单核时代,多线程的这个消除阻塞的作用还可以叫做“并发”,这和并行是有着本质的不同的。并发是“伪并行”,看似并行,而实际上还是一个CPU在执行一切事物,只是切换的太快,我们没法察觉罢了。例如基于UI的程序(俗话说就是图形界面),如果你点一个按钮触发的事件需要执行10秒钟,那么这个程序就会假死,因为程序在忙着执行,没空搭理用户的其他操作;而如果你把这个按钮触发的函数赋给一个线程,然后启动线程去执行,那么程序就不会假死,继续相应用户的其他操作。但是,随之而来的就是线程的互斥和同步、死锁等问题,详细见有关文献。
现在是多核时代了,这种线程的互斥和同步问题是更加严峻的,单核时代大都算并发,多核时代真的就大为不同,为什么呢?具体细节请参考有关文献。我这里简单解释一下,以前volatile型变量的使用可以解决大部分问题,例如多个线程共同访问一个Flag标志位,如果是单核并发,基本不会出问题(P.S.在什么情况下会出问题呢?Flag有多个,或者是一个数组,这时候只能通过逻辑手段搞定这个问题了,多来几次空转无所谓,别出致命问题就行),因为CPU只有一个,同时访问这个标志位的只能有一个线程,而多核情况下就不太一样了,所以仅仅volatile不太能解决问题,这就要用到具体语言,具体环境中的“信号量”了,Mutex,Monitor,Lock等等,这些类都操作了硬件上的“关中断”,达到“原语”效果,对临界区的访问不被打断的效果,具体就不解释了,读者可以看看《现代操作系统》。
(2)并行计算还可以通过其他手段来获得,而多线程只是其中之一。
其他手段包括:多进程(这又包括共享存储区的和分布式多机,以及混合式的),指令级并行。
ILP(指令级并行),x86架构里叫SMT(同时多线程),在MIPS架构里与之对应的是super scalar(超标量)和乱序执行,二者有区别,但共同点都是可以达到指令级并行,这是用户没法控制的,不属于编程范围,只能做些有限的优化,而这有限的优化可能只属于编译器管辖的范畴,用户能做的甚少。
(3)典型的适于并行计算的语言
Erlang和MPI:这两个前者是语言,后者是C++和Fortran的扩展库,效果是一样的,利用多进程实现并行计算,Erlang是共享存储区的,MPI是混合型的。
C#.NET4.0:新版本4.0可以用少量代码实现并行For循环,之前版本需要用很繁琐的代码才能实现同样功能。这是利用了多线程实现并行计算。Java和C#3.5都有线程池(ThreadPool),也是不错的很好用的多线程管理类,可以方便高效的使用多线程。
CUDA,还是个初生牛犊,有很大的发展潜力,只不过就目前其应用领域很有限。其目前只能使用C语言,而且还不是C99,比较低级,不能使用函数指针。个人感觉这由于硬件上天生的局限性(平均每个核心可用内存小,与系统内存通讯时间长),只适用于做科学计算,静态图像处理,视频编码解码,其他领域,还不如高端CPU。等以后GPU有操作系统了,能充分调度GPU资源了,GPU就可以当大神了。游戏中的物理加速,实际上多核CPU也能很好的做到。
温馨提示:内容为网友见解,仅供参考
第1个回答  推荐于2018-04-24
理论上来说你的理解是对的 但是要看软件啊 对多线程优化好的软件 那是相当明显的比如说我用的3DSMAX 它可以运用多线程 并且可以让CPU100%满载运行 那么 i7 有八个线程 和i5 4个线程
就是我用这个软件就可以提升50%左右 向至强的CPU就更强了 主要是软件 软件可以使用多线程那么提升是相当明显的!追问

请问一般都是怎么优化的,能举个例子吗?

还有下面这段代码,为什么线程数调高了,速度反而更慢 - -!

 

追答

你在百度百科上面 看看多线程 就明白了 上面写的 很详细的!

本回答被提问者和网友采纳
第2个回答  2015-11-20
线程中间有个sleep方法。
程序中有死循环而且中间没用sleep所有导致的。循环一次一定要sleep一下。要不他一直占住CPU不释放,导致程序死锁。
在线程里面加上 :
System.Threading.Thread.Sleep(10000);就能解决这个问题了。

c#关于多线程分配CPU的问题
线程中间有个sleep方法。 你肯定是做的死循环而且中间没用sleep所有导致的。循环一次一定要sleep一下。要不他一直占住CPU 在线程里面加上 System.Threading.Thread.Sleep(1000);那没办法。是你函数里面调用有问题,里面没有Sleep(1000);。把CPU一直占主了!写这个的人有点问题 ...

c# 多线程的小问题
线程本身由于创建和切换的开销,采用多线程不会提高程序的执行速度,反而会降低速度,但是对于频繁IO操作的程序,多线程可以有效的并发。对于包含不同任务的程序,可以考虑每个任务使用一个线程。这样的程序在设计上相对于单线程做所有事的程序来说,更为清晰明了,比如生产、消费者问题。在实际的开发中对于...

C# socket服务器端 多线程客户端 如何少量使用CPU
2)建议你利用socket提供的异步回调 socket.BeginXXXXX() socket.EndXXXX 来实现多线程处理 --- 利用异步回调最大的好处是:(1)可以充分利用.net framework 的线程池中I\/O线程,最大限度降低CPU处理开销。曾经做过处理1000多个socket TCP客户端连接的程序,双核CPU平均占用不超过12%(2)网络通信过...

C#中的多线程超时处理实践
在尝试使用计时器解决超时问题时,发现了几个问题:线程浪费、超时期间的CPU浪费以及可能的bug。使用计时器的解决方案并没有完全解决这些问题。随后,引入了`ManualResetEvent`和`AutoResetEvent`来处理多线程通信,实现更高效、简洁的超时处理。使用这两种事件类,可以更灵活地控制线程等待和释放状态,从而避免...

初学C#,现有 多线程处理数据问题: 有1000条记录,每条记录都要这样处理...
额,对于你的问题我只能这么说,使用多线程不但不会提升处理速度,而且会降低数据处理速度!记住,是一定会降低处理速度!你要明白多线程的作用是异步处理,而不是提高速度(哪怕你的cpu是一万核的也白搭,那只能说明你电脑的处理性能很高),因为所谓多线程其实是“伪线程”,创建越多的线程,则会越多...

C#管理大量耗时的线程,内存占用严重
2.多线程问题,每个客户端连接过来的时候都需要开辟一个新的线程去处理客户发来的消息。3.耗时的任务, 感觉关键在于耗时的任务,因为耗时的线程确实会很快消耗掉所有的线程池。首先,耗时是什么造成的,如果是硬盘读写,能否用cache解决?如果是网络问题,能否call back?如果是数据库问题,能否用cluster...

C# 多线程问题
设置全局变量,这个不可取,在多线程中,如果只有一层这样的线程,还可控,如果层数多了,又是加又是减的,根本控制不了。最后出问题都不知道怎么分析,多线程在分析问题时,有些问题还可重现,有些问题十次能重现一次就不错了。也在做这方面的研究,有时间可以交流一下,看看你们的设计。

C#网络编程与多线程的疑问,求指点
1、这种情况下,多线程当然是要把最占用时间的步骤,以及循环的部分,放到线程里。2、其他线程的代码无法直接操作UI线程里的控件。需要使用委托。你具体的需求我不是很清楚。但是我在这里假设一个例子:比如我有个买票的程序,必须每隔2秒,去服务器请求门票的剩余数量。显示在界面上。界面上还有诸如“...

c# 多线程同时写数据表速度变慢的问题
一般涉及网络、磁盘读写的程序采用多线程,计算过程使用多线程尚不划算。高性能并行计算使用c#不行。如果计算量大建议使用编译性语言(推荐使用FORTURN)。 .net属于半编译性平台,效率较低。

高手进~ C# 多线程处理
异步多线程内存释放主要靠自己,C#的垃圾回收机制是,只有当程序段运行完毕后,垃圾回收机制才对程序开辟的内存进行垃圾回收。而多线程内的程序,特别是客户端连接,只要客户端没有断开连接,你的线程就会继续运行,除非断开客户端,线程的生命周期结束,垃圾回收机制才会对该线程产生占用的内存进行回收。如果...

相似回答