91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
# Copyright (c) 2025 ByteDance Ltd. and/or its affiliates.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
# coding: utf-8
|
|
|
|
"""
|
|
Generic parquet/data file helpers that do not depend on cluster-specific settings.
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
from typing import Iterable, List, Optional
|
|
|
|
import pyarrow.fs as pf
|
|
import torch.distributed as dist
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
SUPPORTED_DATA_EXTENSIONS = (".parquet", ".json", ".jsonl")
|
|
|
|
|
|
def select_supported_files(file_paths: Iterable[str]) -> List[str]:
|
|
file_paths = list(file_paths)
|
|
parquet_files = [path for path in file_paths if path.endswith(".parquet")]
|
|
if parquet_files:
|
|
return parquet_files
|
|
return [path for path in file_paths if path.endswith((".json", ".jsonl"))]
|
|
|
|
|
|
def list_local_supported_data_files(data_dir: str) -> List[str]:
|
|
if os.path.isfile(data_dir):
|
|
if not data_dir.endswith(SUPPORTED_DATA_EXTENSIONS):
|
|
raise ValueError(f"Unsupported data file: {data_dir}")
|
|
return [data_dir]
|
|
|
|
if not os.path.isdir(data_dir):
|
|
raise FileNotFoundError(f"Data path does not exist: {data_dir}")
|
|
|
|
files = [
|
|
os.path.join(data_dir, name)
|
|
for name in os.listdir(data_dir)
|
|
if name.endswith(SUPPORTED_DATA_EXTENSIONS)
|
|
]
|
|
return select_supported_files(files)
|
|
|
|
|
|
def init_arrow_fs(parquet_file_path: str) -> pf.FileSystem:
|
|
if parquet_file_path.startswith("hdfs://"):
|
|
raise ValueError(f"Only local parquet files are supported, got remote path: {parquet_file_path}")
|
|
return pf.LocalFileSystem()
|
|
|
|
|
|
def init_arrow_pf_fs(parquet_file_path: str) -> pf.FileSystem:
|
|
return init_arrow_fs(parquet_file_path)
|
|
|
|
|
|
def get_parquet_data_paths_balanced(data_dir_list, rank=0, world_size=1, num_repeat=1):
|
|
all_data_paths = []
|
|
if rank == 0:
|
|
logger.info("Rank 0 is gathering local data file paths...")
|
|
for data_dir in data_dir_list:
|
|
all_data_paths.extend(sorted(list_local_supported_data_files(data_dir)))
|
|
logger.info(f"Total local data files found: {len(all_data_paths)}")
|
|
|
|
if num_repeat > 1:
|
|
original_len = len(all_data_paths)
|
|
all_data_paths = all_data_paths * num_repeat
|
|
logger.info(f"Repeating dataset {num_repeat} times, from {original_len} to {len(all_data_paths)} files.")
|
|
|
|
if world_size > 1 and dist.is_available() and dist.is_initialized():
|
|
object_list = [all_data_paths]
|
|
dist.broadcast_object_list(object_list, src=0)
|
|
return object_list[0]
|
|
|
|
return all_data_paths
|
|
|
|
|
|
def read_parquet_rows(parquet_file, row_group_id: int, columns: Optional[List[str]] = None):
|
|
return parquet_file.read_row_group(row_group_id, columns=columns).to_pylist() |