我有一个执行以下操作的函数:
这是示例代码:
def extract_function(filename):
with open(filename,'r') as f:
input_data=f.readlines()
try:
// some basic searching pattern matching extracting
// dataframe creation with 10 columns and then extracted values are filled in
empty dataframe
// finally df.to_csv()
if __name__ == '__main__':
pool_size = multiprocessing.cpu_count()
filenames=os.listdir("/home/Desktop/input")
pool=multiprocessing.Pool(pool_size)
pool.map(extract_function,filenames)
pool.close()
pool.join()
input 文件夹中的文件总数为4000
。我使用了多重处理,因为使用 for循环正常运行程序会花费一些时间。下面是两种方法的执行时间:
正常CPU处理= 139.22秒
多处理= 18.72秒
我的系统规格为:
英特尔i5第7代,12GB内存,1TB硬盘,Ubuntu 16.04
在运行包含4000个文件的程序时,所有内核都已得到充分使用(每个内核平均占90%)。因此,我决定增加文件大小并重复该过程。这次输入文件号从4000
增加到1,20,000
。但是这一次在运行代码时,cpu的使用在开始时不稳定,一段时间后利用率下降了(平均每个内核的利用率约为10%)。内存利用率也很低,平均最大值为4gb(剩余8gb)。输入4000个文件后,立即写入csv的文件很快,因为我可以立即看到一个跳跃或大约1000个文件或更多。但是当输入120,000个文件时,文件写入速度减慢到300个文件左右,并且这种减慢速度呈线性关系,一段时间后,文件写入速度一下子变为50-70。一直以来,大多数公羊都是免费的。我重新启动了计算机,并尝试使用相同的方法清除任何不需要的僵尸进程,但结果仍然相同。
这是什么原因? 如何对大型文件实现相同的多处理?
注意:
*每个文件大小平均约为300kb。
*正在写入的每个输出文件约为200字节。
*文件总数为4080。因此,总大小约为1.2gb。
*相同的4080个文件被用于复制以获得1,20,000个文件。
*该程序是用于检查大量文件的多重处理的实验。
更新1
我在功能更强大的计算机上尝试了相同的代码。
Intel i7 8th gen 8700、1Tb SSHD和60GB内存。
。文件写入比普通HDD快得多。该程序采用了:
在实验中的某个时间点,我获得了最快的完成时间,为84秒。当时,连续两次尝试给了我一致的结果。认为可能是因为我已正确设置了池大小中的线程因子数,所以我重新启动并再次尝试。但这一次要慢得多。为了提供一个角度,在正常运行期间,一秒钟或两秒钟左右将写入3000-4000个文件,但是这次它在一秒钟内写入600个以下的文件。在这种情况下,也完全不使用撞锤。 即使使用了多处理模块,CPU的平均利用率也只有3-7%。
答案 0 :(得分:2)
与从RAM中运行代码和数据相比,读写磁盘的速度很慢。与运行CPU中内部缓存中的代码和数据相比,它极其慢。
为了加快速度,使用了多个缓存。
(通常,有一种方法可以禁用高速缓存1和2。如果尝试这样做,则会发现读写速度像石头一样下降。)
所以我的猜测是,一旦传递了一定数量的文件,就会耗尽一个或多个缓存,而磁盘I / O成为瓶颈。
要进行验证,您必须将代码添加到tail -n300 /var/solr/logs/solr.log
中以测量3件事:
让extract_function
返回这三个数字的元组,并对其进行分析。我建议不要使用extract_function
来代替map
,这样您就可以在数字可用时立即开始评估。
如果磁盘I / O确实是问题所在,请考虑使用SSD。
答案 1 :(得分:0)
按照ConcurrentModificationException
和@RolandSmith
的建议,我通过用数据帧替换并附加到IO来避免IO连续写入CSV文件。我认为这消除了不一致之处。我按照@selbie
的建议检查了“羽毛” 和“ paraquet” 高性能IO模块,但我认为这是用于将大文件压缩为较小的数据帧结构体。附加选项不存在。
用于 4000个输入文件的程序花费 72秒进行首次执行,然后平均花费 14-15秒之后的所有成功运行。
重新启动系统会清除这些缓存,并使程序在第一次运行时运行速度变慢。
平均新运行时间为72秒。但是,在程序启动后立即将其杀死,然后运行,终止后的第一次空运行需要 40秒。所有连续运行后平均需要14秒。
在新运行期间,所有核心利用率约为 10-13%。但是,在所有成功运行之后,利用率的核心将是 100%。
经检查有1,20,000个文件,它遵循相同的模式。因此,目前,已解决了不一致问题。因此,如果需要将此类代码用作服务器,则应先进行试运行以使CPU / RAM得以缓存,然后才能开始接受API查询以获得更快的结果。