Ray比Python和.multiprocessing都慢得多

时间:2019-11-04 23:28:50

标签: python ray

我上传了13万个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.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秒。

我使用multiprocessing进行此操作:

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有用吗?

2 个答案:

答案 0 :(得分:0)

我从没使用过ray,但是我很自信,我的解释应该是正确的。

原始代码执行简单的json反序列化。该代码主要需要文件IO和少量CPU。 (json反序列化相当快,这就是json是流行的交换格式的原因之一)

Ray必须将数据从一个进程推送到另一个进程(如果通过网络分布在多台计算机上)。为了做到这一点,它自己执行一些序列化/反序列化(也许它正在使用pickle和强大的TCP协议来推送参数并收集结果)。可能比实际任务需要的工作量更大。

如果您将对json数据进行更多的计算(任何需要占用更多CPU的资源),那么您将能够看到不同之处。

我的猜测是,您的示例问题太简单了,因此ray的开销超出了使用多个工作程序的好处。

换句话说。分配任务和收集结果所花费的时间/精力比执行计算结果所花费的时间/精力更多。

答案 1 :(得分:0)

我要说的是,假设1)最接近真相。 Ray似乎是一个功能强大的库,但是您要做的只是读取一堆文件。您的代码仅仅是为了进行基准测试的示例,还是更大程序的一部分?如果是后者,那么让您的基准代码反映出来可能会很有趣。

没什么大不了的,但是我对您的3个程序进行了调整,因此它们至少应该有更高的效率。


import os
import json


folder_path = "/my_path/"
filename_ending = '.json'

json_files = (os.path.join(folder_path, fp) for fp in os.listdir(f"{folder_path}") if fp.endswith(filename_ending))


def load_json_from_file(file_path):
    with open(file_path, 'r') as file_1:
        return json.load(file_1)


json_list = [load_json_from_file(curr_fp) for curr_fp in json_files]

import os
import json
import multiprocessing as mp


folder_path = "/my_path/"
filename_ending = '.json'

json_files = (os.path.join(folder_path, fp) for fp in os.listdir(f"{folder_path}") if fp.endswith(filename_ending))


def load_json_from_file(file_path):
    with open(file_path, 'r') as file_1:
        return json.load(file_1)


with mp.Pool() as pool:       
    json_list = pool.map(load_json_from_file, json_files)  

import os
import json
import ray

folder_path = "/my_path/"
filename_ending = '.json'


@ray.remote
def load_json_from_file(file_path):
    with open(file_path, 'r') as file_1:
        return json.load(file_1)


json_files = (os.path.join(folder_path, fp) for fp in os.listdir(f"{folder_path}") if fp.endswith(filename_ending))

ray.init()

futures_list = [load_json_from_file.remote(curr_fp) for curr_fp in json_files]

json_list = ray.get(futures_list)

如果您有任何疑问,请告诉我。如果您可以再次运行基准测试,我很想知道有什么区别(如果有)。