Write burden CSV shards in workers
This commit is contained in:
@@ -586,6 +586,26 @@ def _project_bi_rows(
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _write_rows_csv(rows: list[dict[str, Any]], output_path: Path) -> int:
|
||||||
|
df = pd.DataFrame(rows)
|
||||||
|
df.to_csv(output_path, index=False)
|
||||||
|
return int(len(df))
|
||||||
|
|
||||||
|
|
||||||
|
def _concat_csv_shards(shard_paths: list[Path], output_path: Path) -> None:
|
||||||
|
wrote_header = False
|
||||||
|
with output_path.open("w", encoding="utf-8", newline="") as out_f:
|
||||||
|
for shard_path in shard_paths:
|
||||||
|
with shard_path.open("r", encoding="utf-8", newline="") as in_f:
|
||||||
|
header = in_f.readline()
|
||||||
|
if not wrote_header:
|
||||||
|
out_f.write(header)
|
||||||
|
wrote_header = True
|
||||||
|
for line in in_f:
|
||||||
|
out_f.write(line)
|
||||||
|
shard_path.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def _compute_bi_from_streamed_readouts(
|
def _compute_bi_from_streamed_readouts(
|
||||||
*,
|
*,
|
||||||
rows: list[dict[str, Any]],
|
rows: list[dict[str, Any]],
|
||||||
@@ -710,6 +730,7 @@ def _compute_bi_from_streamed_readouts(
|
|||||||
def _compute_chunk_worker(payload: dict[str, Any]) -> dict[str, Any]:
|
def _compute_chunk_worker(payload: dict[str, Any]) -> dict[str, Any]:
|
||||||
device = payload["device"]
|
device = payload["device"]
|
||||||
run_path = Path(payload["run_path"])
|
run_path = Path(payload["run_path"])
|
||||||
|
shard_path = Path(payload["shard_path"])
|
||||||
print(
|
print(
|
||||||
f"[BI worker {device}] starting with {len(payload['row_specs'])} rows",
|
f"[BI worker {device}] starting with {len(payload['row_specs'])} rows",
|
||||||
flush=True,
|
flush=True,
|
||||||
@@ -745,7 +766,20 @@ def _compute_chunk_worker(payload: dict[str, Any]) -> dict[str, Any]:
|
|||||||
f"reduce={timings['reduce_sec']:.2f}s",
|
f"reduce={timings['reduce_sec']:.2f}s",
|
||||||
flush=True,
|
flush=True,
|
||||||
)
|
)
|
||||||
return {"rows": out, "readout_jobs": readout_jobs, "timings": timings}
|
write_start = time.perf_counter()
|
||||||
|
row_count = _write_rows_csv(out, shard_path)
|
||||||
|
timings["write_csv_sec"] = time.perf_counter() - write_start
|
||||||
|
print(
|
||||||
|
f"[BI worker {device}] wrote {row_count} rows to {shard_path} "
|
||||||
|
f"in {timings['write_csv_sec']:.2f}s",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"shard_path": str(shard_path),
|
||||||
|
"row_count": row_count,
|
||||||
|
"readout_jobs": readout_jobs,
|
||||||
|
"timings": timings,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _attach_union_projection(
|
def _attach_union_projection(
|
||||||
@@ -959,8 +993,9 @@ def main() -> None:
|
|||||||
)
|
)
|
||||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
all_rows: list[dict[str, Any]] = []
|
|
||||||
total_readout_jobs = 0
|
total_readout_jobs = 0
|
||||||
|
output_written = False
|
||||||
|
shard_paths: list[Path] = []
|
||||||
total_timings = {
|
total_timings = {
|
||||||
"build_readout_sec": 0.0,
|
"build_readout_sec": 0.0,
|
||||||
"forward_sec": 0.0,
|
"forward_sec": 0.0,
|
||||||
@@ -1000,6 +1035,10 @@ def main() -> None:
|
|||||||
)
|
)
|
||||||
for key, value in timings.items():
|
for key, value in timings.items():
|
||||||
total_timings[key] += float(value)
|
total_timings[key] += float(value)
|
||||||
|
write_start = time.perf_counter()
|
||||||
|
_write_rows_csv(all_rows, output_path)
|
||||||
|
total_timings["write_csv_sec"] = time.perf_counter() - write_start
|
||||||
|
output_written = True
|
||||||
else:
|
else:
|
||||||
# The main-process context is only needed to build the dataset and rows.
|
# The main-process context is only needed to build the dataset and rows.
|
||||||
# Workers load their own model copy on the assigned device.
|
# Workers load their own model copy on the assigned device.
|
||||||
@@ -1008,6 +1047,11 @@ def main() -> None:
|
|||||||
{
|
{
|
||||||
"device": device,
|
"device": device,
|
||||||
"run_path": str(run_path),
|
"run_path": str(run_path),
|
||||||
|
"shard_path": str(
|
||||||
|
output_path.with_name(
|
||||||
|
f"{output_path.stem}.part{part_idx:03d}{output_path.suffix}"
|
||||||
|
)
|
||||||
|
),
|
||||||
"row_specs": [_row_to_worker_spec(row) for row in chunk_rows],
|
"row_specs": [_row_to_worker_spec(row) for row in chunk_rows],
|
||||||
"horizon": horizon,
|
"horizon": horizon,
|
||||||
"matrices": matrices,
|
"matrices": matrices,
|
||||||
@@ -1016,7 +1060,7 @@ def main() -> None:
|
|||||||
"num_workers": int(args.num_workers),
|
"num_workers": int(args.num_workers),
|
||||||
"formed_mode": args.formed_mode,
|
"formed_mode": args.formed_mode,
|
||||||
}
|
}
|
||||||
for device, chunk_rows in row_chunks
|
for part_idx, (device, chunk_rows) in enumerate(row_chunks)
|
||||||
]
|
]
|
||||||
with ProcessPoolExecutor(
|
with ProcessPoolExecutor(
|
||||||
max_workers=len(payloads),
|
max_workers=len(payloads),
|
||||||
@@ -1030,15 +1074,18 @@ def main() -> None:
|
|||||||
dynamic_ncols=True,
|
dynamic_ncols=True,
|
||||||
):
|
):
|
||||||
result = future.result()
|
result = future.result()
|
||||||
all_rows.extend(result["rows"])
|
shard_paths.append(Path(result["shard_path"]))
|
||||||
total_readout_jobs += int(result["readout_jobs"])
|
total_readout_jobs += int(result["readout_jobs"])
|
||||||
for key, value in result["timings"].items():
|
for key, value in result["timings"].items():
|
||||||
total_timings[key] += float(value)
|
total_timings[key] += float(value)
|
||||||
|
|
||||||
write_start = time.perf_counter()
|
write_start = time.perf_counter()
|
||||||
out_df = pd.DataFrame(all_rows)
|
_concat_csv_shards(sorted(shard_paths), output_path)
|
||||||
out_df.to_csv(output_path, index=False)
|
total_timings["write_csv_sec"] += time.perf_counter() - write_start
|
||||||
total_timings["write_csv_sec"] = time.perf_counter() - write_start
|
output_written = True
|
||||||
|
|
||||||
|
if not output_written:
|
||||||
|
raise RuntimeError("BI output was not written.")
|
||||||
print(f"Run path: {run_path}")
|
print(f"Run path: {run_path}")
|
||||||
print(f"Eval split: {eval_split}")
|
print(f"Eval split: {eval_split}")
|
||||||
print(f"Horizon: {horizon:g}")
|
print(f"Horizon: {horizon:g}")
|
||||||
|
|||||||
Reference in New Issue
Block a user