【发布时间】:2022-01-07 11:33:13
【问题描述】:
我正在解析称为 FCD 的巨大 XML 文件(> 400 MB,~7M 行),它是 SUMO 道路交通模拟器的输出。 我的目标是及时获取每辆车的位置。
示例 FCD 文件如下所示:
<fcd-export>
<timestep time="0.00">
<vehicle id="flow_0.0" x="605.79" y="1142.59"/>
<vehicle id="flow_1.0" x="1911.72" y="2154.71"/>
<vehicle id="flow_3.0" x="1907.24" y="2163.97"/>
</timestep>
<timestep time="0.10">
<vehicle id="flow_0.0" x="605.81" y="1142.61"/>
<vehicle id="flow_1.0" x="1911.70" y="2154.69"/>
<vehicle id="flow_3.0" x="1907.22" y="2163.95"/>
</timestep>
<timestep time="0.20">
<vehicle id="flow_0.0" x="605.85" y="1142.64"/>
<vehicle id="flow_1.0" x="1911.66" y="2154.66"/>
<vehicle id="flow_3.0" x="1907.18" y="2163.92"/>
</timestep>
</fcd-export>
我正在将其解析为此类 dicts 的列表:{car_id, time, x, y} 使用 lxml 和 multiprocessing 库,它们工作正常,36000 个时间步长约 30 秒,XML 文件中约 7M 行。我在底部附加了parse_fcd() 函数。结果列表有 680 万个项目。
现在我需要映射那些[time, car_id, x, y] 项目以及时获得每辆车的所有位置。我创建了简单的类来存储这些数据:
class CarInfo:
car_id: str
time_locations: List[TimeLocation]
class TimeLocation:
time: float
x: float
y: float
我尝试使用以下代码进行映射:
import multiprocessing as mp
from typing import List
def extract_car_infos_parallel(car_time_location_items: List[dict]) -> List[CarInfo]:
car_ids = set(map(lambda item: item['car_id'], car_time_location_items))
pool = mp.Pool(mp.cpu_count())
car_infos = pool.starmap(extract_time_location_items_for_car, [(car_id, car_time_location_items) for car_id in car_ids])
pool.close()
pool.join()
return car_infos
def extract_time_location_items_for_car(car_id: str, all_items: List[dict]) -> CarInfo:
car = CarInfo(car_id)
items_for_car = list(filter(lambda item: item['car_id'] == car_id, all_items))
car.time_locations = [TimeLocation(item['time'], item['x'], item['y']) for item in items_for_car]
return car
代码运行大约 15 分钟并抛出 BrokenPipeError。我尝试将 dicts {car_id, time, x, y} 列表更改为具有这些值的列表列表,结果相同。
如何解决此问题以摆脱 BrokenPipeError 并加快速度?
PS:
这是从 XML 文件中解析 FCD 数据的代码:
from lxml import etree
from lxml.etree import XMLParser, parse
import multiprocessing as mp
from typing import List
def parse_fcd_data_parallel(fcd_file: str) -> List[dict]:
p = XMLParser(huge_tree=True)
xml_data = parse(fcd_file, parser=p)
fcd_data = xml_data.getroot()
pool = mp.Pool(mp.cpu_count())
results = pool.map(parse_fcd_timestep, [timestep for timestep in fcd_data])
pool.close()
pool.join()
flatten_results = [item for sublist in results for item in sublist]
return flatten_results
def parse_fcd_timestep(timestep) -> List[dict]:
car_time_location_items: List[dict] = []
time_stamp = timestep.get('time')
for raw_car_info in timestep:
car_id = raw_car_info.get('id')
pos_x = raw_car_info.get('x')
pos_y = raw_car_info.get('y')
car_time_location_items.append({'car_id': car_id, 'time': time_stamp, 'x': pos_x, 'y': pos_y})
return car_time_location_items
【问题讨论】:
-
欢迎,@krzycho2 - 您对 [TIME] 和给定 [SPACE] 域约束的目标性能的定量表达期望是什么,以及 w.r.t.考虑到可用的 RAM 大小和 CPU 内核,潜在的输入会扩大吗?
标签: python parallel-processing sumo