论坛首页 Java企业应用论坛

淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和

浏览 94793 次
该帖已经被评为良好帖
作者 正文
   发表时间:2010-07-13   最后修改:2010-07-13
飞雪无情 写道
mercyblitz 写道
pengpeng99bill 写道
这还是 多线程的问题 啊 还是没有解决多CPU处理的问,你的多线程怎么能保证是多个CPU在处理呢 ,可能还是一个CPU在处理啊 。以前看到过报道好像说是 java7 支持多CPU处理任务。 等待中。。。



可能,你误会了。Java 1.2之后,使用的操作系统内核线程,操作系统还是会利用多CPU的,也就是说和Java无关了。
我的《Java内存模型》正在写,其中起到了这些东西,如果有需要的话,可以关注一下。


回帖里有好多说多CPU的,我不清楚说的是多个CPU,还是一个CPU多个核理解成多CPU了,我的题目是多核CPU,是一个CPU多个核,不知道是不是你们所理解的多CPU。

就像上面说的,操作系统内核线程由操作系统负责调配的,会充分的利用多核,CPU自己也会控制。


多个CPU是指那个主板能够插入多个CPU,比如刀片机。
多核CPU是指一个CPU上面有多个处理器,比如PC机。

无论哪种结构,都属于单独的处理器,并发计算的。
0 请登录后投票
   发表时间:2010-07-13  
dilantaya 写道
melody3 写道
kakaluyi 写道
amigo 写道
dilantaya 写道
sunwenran 写道
赞一个。

问题是我用你的例子比较直接加
        long noCurrentSum=0L;  
        for(Integer i:list){  
            noCurrentSum+=i;  
        } 
发现时间差不多。而且有时候直接加更快。纠结了。。我的是双核。


可能是你给的数据量还不够大


调整到50000000
for (int i = 1; i <= 50000000; i++) {
list.add(i);
}


单线程时间比并发更快

呵呵其实这种纯粹的算术相加速度单线程和多线程是一样的(因为没有io读写,没有网络等待等等,),新建线程还要消耗资源,如何设计利用多核cpu就涉及到jvm的底层实现了,所以要我回答这个问题,我给出下面答案:
int sum=0;
for(int i=0;i<list.size();i++)
{
sum+=list.get(i);
}
return sum;


这个就是常规的求值啊


同问

   因为比如说list有100个整数对象,平均一次加运算耗费1秒吧(夸张点)。你分成10个线程去计算,每个线程运行10秒钟计算完自己的线程(自己计算的同时cpu时间片是不可能分给其他线程的)那么10个线程需要100秒,一个线程100次相加运算,因为是从内存读出数据,我们可以忽略等待时间,那么也是100秒,但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的。
   如果该问题是从10000个文件(更比如说是webservice从别的异构系统读出整数)读出数字相加,我肯定会用lz的方法,因为读取文件需要io时间,这些线程等待的时候,其他线程还可以进行运算,不会像单线程阻塞住,这时候才是多线程应用的场景,个人看法,欢迎拍砖
2 请登录后投票
   发表时间:2010-07-13  
多线程的时间都浪费在启动线程上面了。做多了很多无用功,当然海量数据还是有用的。10亿以下的就算了
0 请登录后投票
   发表时间:2010-07-13  
kakaluyi 写道

   因为比如说list有100个整数对象,平均一次加运算耗费1秒吧(夸张点)。你分成10个线程去计算,每个线程运行10秒钟计算完自己的线程(自己计算的同时cpu时间片是不可能分给其他线程的)那么10个线程需要100秒,一个线程100次相加运算,因为是从内存读出数据,我们可以忽略等待时间,那么也是100秒,但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的。
   如果该问题是从10000个文件(更比如说是webservice从别的异构系统读出整数)读出数字相加,我肯定会用lz的方法,因为读取文件需要io时间,这些线程等待的时候,其他线程还可以进行运算,不会像单线程阻塞住,这时候才是多线程应用的场景,个人看法,欢迎拍砖


> 但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的
弱问一下, 这句是说多线程其实比单线程还慢的原因吗?

> 自己计算的同时cpu时间片是不可能分给其他线程的
对于多核CPU,这句怎么解释?

> 但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间
闭锁(Latch)让控制线程能够等待最后一个线程完成任务, 而不是顺序等待每一个线程结束。


wujiazhao88 写道
多线程的时间都浪费在启动线程上面了。做多了很多无用功,当然海量数据还是有用的。10亿以下的就算了


有道理, 创建线程确实是一个很大的开销, 但在海量计算时, 是有优势的. 多少以下, 需按情况来定嗯.
0 请登录后投票
   发表时间:2010-07-13   最后修改:2010-07-13
quote="david.org"]
kakaluyi 写道

   因为比如说list有100个整数对象,平均一次加运算耗费1秒吧(夸张点)。你分成10个线程去计算,每个线程运行10秒钟计算完自己的线程(自己计算的同时cpu时间片是不可能分给其他线程的)那么10个线程需要100秒,一个线程100次相加运算,因为是从内存读出数据,我们可以忽略等待时间,那么也是100秒,但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的。
   如果该问题是从10000个文件(更比如说是webservice从别的异构系统读出整数)读出数字相加,我肯定会用lz的方法,因为读取文件需要io时间,这些线程等待的时候,其他线程还可以进行运算,不会像单线程阻塞住,这时候才是多线程应用的场景,个人看法,欢迎拍砖

> 但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的
弱问一下, 这句是说多线程其实比单线程还慢的原因吗?
是说lz这个场景下单线程实现不会比多线程实现快的原因,这种场景我觉得用单线程足以.

> 自己计算的同时cpu时间片是不可能分给其他线程的
对于多核CPU,这句怎么解释?
确实多核的cpu要多线程才能发挥优势

> 但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间
闭锁(Latch)让控制线程能够等待最后一个线程完成任务, 而不是顺序等待每一个线程结束。
闭锁等待最后一个线程完成任务的实现也需要消耗资源,可能我没有说明白,需要专门去判断所有线程已经结束
wujiazhao88 写道
多线程的时间都浪费在启动线程上面了。做多了很多无用功,当然海量数据还是有用的。10亿以下的就算了


有道理, 创建线程确实是一个很大的开销, 但在海量计算时, 是有优势的. 多少以下, 需按情况来定嗯.

0 请登录后投票
   发表时间:2010-07-13  
wujiazhao88 写道
多线程的时间都浪费在启动线程上面了。做多了很多无用功,当然海量数据还是有用的。10亿以下的就算了


你这个数据有比较臆断啊,10亿以上则需要?

那么多数据,都需要多节点了。
0 请登录后投票
   发表时间:2010-07-13  
kakaluyi 写道
quote="david.org"]
kakaluyi 写道

   因为比如说list有100个整数对象,平均一次加运算耗费1秒吧(夸张点)。你分成10个线程去计算,每个线程运行10秒钟计算完自己的线程(自己计算的同时cpu时间片是不可能分给其他线程的)那么10个线程需要100秒,一个线程100次相加运算,因为是从内存读出数据,我们可以忽略等待时间,那么也是100秒,但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的。
   如果该问题是从10000个文件(更比如说是webservice从别的异构系统读出整数)读出数字相加,我肯定会用lz的方法,因为读取文件需要io时间,这些线程等待的时候,其他线程还可以进行运算,不会像单线程阻塞住,这时候才是多线程应用的场景,个人看法,欢迎拍砖

> 但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间,其实多线程是比单线程还慢的
弱问一下, 这句是说多线程其实比单线程还慢的原因吗?
是说lz这个场景下单线程实现不会比多线程实现快的原因,这种场景我觉得用单线程足以.

> 自己计算的同时cpu时间片是不可能分给其他线程的
对于多核CPU,这句怎么解释?
确实多核的cpu要多线程才能发挥优势

> 但是扣除你新建线程的消耗和最后等待所有线程运行完才能最后求整的时间
闭锁(Latch)让控制线程能够等待最后一个线程完成任务, 而不是顺序等待每一个线程结束。
闭锁等待最后一个线程完成任务的实现也需要消耗资源,可能我没有说明白,需要专门去判断所有线程已经结束
wujiazhao88 写道
多线程的时间都浪费在启动线程上面了。做多了很多无用功,当然海量数据还是有用的。10亿以下的就算了


有道理, 创建线程确实是一个很大的开销, 但在海量计算时, 是有优势的. 多少以下, 需按情况来定嗯.



每一个线程需要占据内存,如果太多确实会影响性能,一般用线程池啦,固定Core的大小。
0 请登录后投票
   发表时间:2010-07-13  
tamsiuloong 写道
真的很讨厌je拷贝代码时,前有行数号。讨厌之极 啊


是你自己傻。点击按钮就行了。
0 请登录后投票
   发表时间:2010-07-13  
int len=list.size()/threadCounts;//平均分割List 
        //List中的数量没有线程数多(很少存在) 
        if(len==0){ 
            threadCounts=list.size();//采用一个线程处理List中的一个元素 
            len=list.size()/threadCounts;//重新平均分割List 
        } 
可以在这里添加下面的代码就把不能整除的问题也考虑了
    len=list.size()%threadCounts==0?list.size()/threadCounts:list.size()/threadCounts+1;
0 请登录后投票
   发表时间:2010-07-13   最后修改:2010-07-13
精彩!精彩的发帖!精彩的回复!好久没在JE上见过这么精彩的贴了
我只是打酱油的...
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics