Ray比Python和.multiprocessing都慢得多
我上传了130k个json文件 我使用Ray比Python和.multiprocessing都慢得多,python,ray,Python,Ray,我上传了130k个json文件 我使用Python: import os import json import pandas as pd path = "/my_path/" filename_ending = '.json' json_list = [] json_files = [file for file in os.listdir(f"{path}") if file.endswith(filename_ending)] import time start = time.ti
Python
:
import os
import json
import pandas as pd
path = "/my_path/"
filename_ending = '.json'
json_list = []
json_files = [file for file in os.listdir(f"{path}") if file.endswith(filename_ending)]
import time
start = time.time()
for jf in json_files:
with open(f"{path}/{jf}", 'r') as f:
json_data = json.load(f)
json_list.append(json_data)
end = time.time()
这需要60秒
我通过多处理来实现这一点:
import os
import json
import pandas as pd
from multiprocessing import Pool
import time
path = "/my_path/"
filename_ending = '.json'
json_files = [file for file in os.listdir(f"{path}") if file.endswith(filename_ending)]
def read_data(name):
with open(f"/my_path/{name}", 'r') as f:
json_data = json.load(f)
return json_data
if __name__ == '__main__':
start = time.time()
pool = Pool(processes=os.cpu_count())
x = pool.map(read_data, json_files)
end = time.time()
这需要53秒
我使用ray
:
import os
import json
import pandas as pd
from multiprocessing import Pool
import time
import ray
path = "/my_path/"
filename_ending = '.json'
json_files = [file for file in os.listdir(f"{path}") if file.endswith(filename_ending)]
start = time.time()
ray.shutdown()
ray.init(num_cpus=os.cpu_count()-1)
@ray.remote
def read_data(name):
with open(f"/my_path/{name}", 'r') as f:
json_data = json.load(f)
return json_data
all_data = []
for jf in json_files:
all_data.append(read_data.remote(jf))
final = ray.get(all_data)
end = time.time()
这需要146秒
我的问题是为什么ray花了这么多时间
是否因为:
1) 对于相对较小的数据量,光线速度相对较慢
2) 我的代码有问题吗
3) ray
没有那么有用吗?我从未使用过ray,但我很有信心,我的解释应该是正确的
原始代码执行简单的json反序列化。该代码主要需要文件IO和少量CPU。(json反序列化相当快,这就是为什么json是一种流行的交换格式的原因之一)
Ray必须将数据从一个进程推送到另一个进程(如果通过网络分布在多台机器上)。为此,它自己执行一些序列化/反序列化(可能是使用pickle和健壮的TCP协议来推送参数和收集结果)。而且这个开销可能比实际任务所需的工作量更大
如果您对json数据进行更多的计算(任何CPU更密集的数据),那么您将能够看到不同之处
我的猜测是,您的示例问题太简单,因此ray的开销超过了使用多个worker的好处
换句话说。分配任务和收集结果所花费的时间/精力比计算结果实际花费的时间/精力要多。我认为假设1)可能最接近事实。Ray似乎是一个功能强大的库,但你所做的只是读取一堆文件。您的代码只是为了基准测试的一个示例,还是某个更大程序的一部分?如果是后者,那么让您的基准代码反映这一点可能会很有趣
这没什么大不了的,但我调整了你的3个程序,所以它们至少应该稍微有点效率
导入操作系统
导入json
folder_path=“/my_path/”
filename_ending='.json'
json_files=(os.path.join(folder_path,fp)用于os.listdir(f“{folder_path}”)中的fp,如果fp.endswith(filename_ending))
def从_文件加载_json_(文件路径):
打开(文件路径“r”)作为文件“1”:
返回json.load(文件1)
json_list=[从_文件(curr_fp)为json_文件中的curr_fp加载_json_]
导入操作系统
导入json
将多处理作为mp导入
folder_path=“/my_path/”
filename_ending='.json'
json_files=(os.path.join(folder_path,fp)用于os.listdir(f“{folder_path}”)中的fp,如果fp.endswith(filename_ending))
def从_文件加载_json_(文件路径):
打开(文件路径“r”)作为文件“1”:
返回json.load(文件1)
使用mp.Pool()作为池:
json_list=pool.map(从_文件、json_文件加载_json_)
导入操作系统
导入json
导入光线
folder_path=“/my_path/”
filename_ending='.json'
@雷,遥控器
def从_文件加载_json_(文件路径):
打开(文件路径“r”)作为文件“1”:
返回json.load(文件1)
json_files=(os.path.join(folder_path,fp)用于os.listdir(f“{folder_path}”)中的fp,如果fp.endswith(filename_ending))
ray.init()
futures_list=[从_file.remote(curr_fp)为json_文件中的curr_fp加载_json_]
json_list=ray.get(futures_list)
如果你有任何问题,请告诉我。如果你能再次运行基准测试,我很想知道有什么不同,如果有的话。@RobertNishihara,有什么想法吗?Ray是分布式计算库,对吗?@AlexanderCécile,是的:)好的,我目前正在做一些快速的研究,并试图写出一个答案:)你能分享一个JSON文件进行测试吗?你怎么知道Ray正在做任何与网络相关的事情?我不知道,如果它在一台主机上运行,它是否真的在联网,如果它使用集群的话。对于单主机设置,它可能只是本地TCP套接字、unix域套接字、本地管道或共享内存。但在大多数情况下,串行化、反串行化、交换数据和同步都会有相当大的开销。我修改了我的回答我很确定Ray使用Redis服务器来处理进程间的通信,即使是本地的,所以启动时可能会受到不可忽视的损失。再加上这里绝大多数工作都是文件系统I/O,我很有信心@gelonida是正确的。嘿,谢谢你的回复(upvote)。我同意假设(1)在我的案例中更为正确,尽管有证据证明,Ray
在数据较大的情况下实际上更好。顺便问一下,关于你的第二段代码,你为什么不使用\uuuu main\uuuu
?我认为(根据它的文档)要使用多处理
就必须使用\uuuuu main\uuuu
?@PoeteMaudit Oops,我忘记了这个评论,对不起!在Windows上使用多处理
时,\uuuuuu main\uuuuuu
似乎是绝对必要的。我用的是Mac电脑,但对我来说编写\uuuu main\uuuu
部分可能是个好主意。请参阅,以了解为什么它在Windows上是必须的,以及关于这个主题的更一般性的讨论。很酷,但我也使用它运行了多处理:使用mp.Pool(processs=os.cpu\u count()-1)作为Pool:output=Pool.map(my\u函数,input)
那么没有\uuuuu main\uuuu
@PoeteMaudit,你就不用Windows了吗?啊,是的,这是一个很好的观点。我在远程服务器上运行它,所以我不知道它是什么。我想是Linux吧?