a的n次方一个生成10的N次方个整数的一段小程序 彰
a的n次方一个生成10的N次方个
整数的一段小程序 彰
2011-06-26 a的n次方一个生成10的N次方个整数的一段小程序,彰显出的大智慧a的n次方一个生成10的N次方个整数的一段小程序,彰显出的大智慧
魏仁言2010.8.28
最近在学习Hadoop,上次用Map/Reduce模型写个了对大量整数数字求和的程序,为了测试就要生成大量测试数据,我用Ruby写了个随机生成整数,并将整数按指定的格式写入文本文件,然后将生成的数据输入Map/Reduce程序(NumerSum),进行求和。针对这样的小功能我相信学过编程的都能写出来,因为这个问题很简单,实际要做的就是给定一个数值N,它来定义生成的数据量,当N=3时,就是生成1000个随机数字然后将数据写入文件,生成过程用For循环,循环个1000次就可以了。我想要的结果是生成的数据文=10M,最低要求至少N=5,反正是多多益善。现在问题与相应的解决方法也有了,下面我就逐步介绍下我的整个实现过程。
问题:生成一个包含有10的N次方个整数的文本文件,N可以无限大,程序的运行时间要在可以忍受的程度,就是说程序的性能要求比较高。
解决方法:
1.定义一个数组m,通过Random生成随机数n,将数值n存入数组m内,并且随机数要包含有负数,限定随机数n值在-99=
2.从数组m内,读取生成的结果,写入文件num.txt
我分别用两种方式去实现我的代码,第1种方式是用简单的循环方法实现的,第2种方式是用多线程将要生成的整数任务,分解成多个小任务,分配给T个线程去执行,每个线程执行完成后,将其运行结果进行输出到指定的文件内。
第一种实现代码#~/usr/bin/ruby puts"Hello,World.\n";#写文件方法
def
write(filename,context)out=File.open(filename,"a")out.write(context)out.close end start=Time.now puts"Start.#{start}"n=10*5 nmu=""a=#生成
数组数值for iin 0.n-1 if i%3==0&&i%2==0 a[i]=-rand(100)elsif i%4==0&&i%5==0 a[i]=-rand(100)#a[i-1]=-a[i-1]else a[i]=rand(100)end end#puts a.join("")#读取数组内的值,写入文件i=0 while i=n-1 u=n-1
end#每一行10个整数str=a[i.u].join("")+"\n"write("num.txt",str)#puts str i+=10 end ed=Time.now cs=ed-start
puts"End.#{ed}"puts"Consnum.#{cs}s\n\n"#puts a.join("")#打印所有整数
的和s=0 a.each do|i|s+=i end puts s第二种实现代码#~/usr/bin/ruby
;#写文件方法def require'thread'puts"Hello,World.\n"
write(filename,context)out=File.open(filename,"a")out.write(context)out.close end#将生成的数据写入文件def writeArr(arr)i=0 n=arr.length
str=""while i=n-1 u=n-1 end#每一行10个数字
str=str+arr[i.u].join("")+"\n"#缓存处理写文件
if((u+1)%(200000)==0)||(u==n-1)write("num.txt",str)str=""end i+=10 end end threads=n=6#生成整数的数量N=10*n#线程数量T=4*10*(2)#n:5,T:
20;n:6,T:600;n:7,T,7000 mutex=Mutex.new starts=Time.now
puts"Start Threads.#{starts}"T.times{|i|#定义线程threads
Thread.new(i){puts iarr=count=0 l=0 u=N/T#每个线程要生成的整数数量
start=Time.now puts"Start Thread-#{i}.#{start}"loop
do#mutex.synchronize do#puts count if count u-1#puts
arr.join("")ed=Time.now cs=ed-start puts"End Thread-
#{i}.#{ed}"puts"Consnum.#{cs}s\n\n"puts count-1#mutex.synchronize do writeArr(arr)#end tt=Thread.current tt.exit end#随机生成整数
index=count if index%3==0&&index%2==0 arr[index]=-rand(10000)elsif index%4==0&&index%5==0 arr[index]=-rand(10000)#arr[index-1]=-arr[index-1]else arr[index]=rand(10000)end count+=1#end end}#运行线程
threads[i].run}puts"Init Complete"threads.each{|t|t.join}eds=Time.now css=eds-starts puts"End
Threads.#{eds}"puts"Consnum.#{css}s\n\n"puts"Done Complete"程序运行结果:
生成100000个整数,N=5时,
实现1.9.39s
实现2.1.453 s
我们都知道通过多线程并行计算的方式,可以提高程序运行的性能。当我用"实现1"去计算10^10个整数时,运行时间太长了,所以我就想能否用线程的方式,来缩短运行时间,这时我就快速地想出了"实现2"的大体思路,并将代码写出来,写出后运行结果与我预想的太差了,运行时间比"实现1"要多好几倍,经过多次调试,我终于明白了问题所在,并最终明白其内部所体现的智慧。
运行性能关键点:
1.线程的数量
2.每个线程要生成整数的数量
3.并行频繁地写入文件,文件写入等待
针对问题所在,我的处理措施如下:我通过对要生成整数的数量,指定相应线程数量及每个线程要处理的数量,
1.任务分解:
每个线程要生成整数的数量=要生成整数的数量/运行线程的数量
一定数量的整数生成,要有相应的线程去运行,不能多也不能少,少的话每个线程的任务太重,太少则线程对象自身的创建与销毁就占了太多时间,有点反客为主的意思。
例如:当N=5时,T=20,运行时间1.453s:
当N=5时,T=50,运行时间1.563s
当N=6时,T=50,运行时间39.141 s
当N=6时,T=200,运行时间21.36s
运行时间15.922 s 当N=6时,T=500,
当N=6时,T=600,运行时间16.593 s
2.运用缓存:
当线程数量太大的时候,大家都去写文件,这时为了等待写入文件的时间,就占用整个生成时间70%还多;我通过缓存的方式,在写入文件时,每次读取20000个整数写一次,直到读完为至;不是每读取一个整数就写进去。
例如:当N=5时,T=50,运行时间15.656 s://没有用缓存机制
当N=5时,T=50,运行时间1.563s://用缓存机制
在学习的过程中,我理解到在用Hadoop处理数据时,用Map方法,对输入数据进行分解很重要,以及要用多少个Map Tasker,这个数量一定要根据输入数据量的大小来指定。在数据输出时,可以对其进行多次合并,减少数据输出量,从而提高整个程序运行性能。
注:如需转载,请注明出处,谢谢。
历史上的今天:
乌鲁木齐市住房公积金新疆维乌尔自治区2011-06-26