Diffusers
Safetensors
AR / utils /autodataloader.py
xfcghj's picture
Upload folder using huggingface_hub
f0fc238 verified
Raw History Blame Contribute Delete
3.03 kB
import os
import glob
import tarfile
import pickle
import zstandard
import torch
from torch.utils.data import IterableDataset, DataLoader
class DyMeshIterableDataset(IterableDataset):
def __init__(self, data_dir, rank=0, world_size=1):
super(DyMeshIterableDataset, self).__init__()
# 获取所有分片文件
self.tar_paths = sorted(glob.glob(os.path.join(data_dir, "shard_*.tar.zst")))
# 根据 Rank 进行数据切分
self.my_tar_paths = [p for i, p in enumerate(self.tar_paths) if i % world_size == rank]
print(f"[Rank {rank}] 负责处理 {len(self.my_tar_paths)} 个分片")
def __iter__(self):
worker_info = torch.utils.data.get_worker_info()
# 根据 Worker 进行数据切分
if worker_info is None:
curr_paths = self.my_tar_paths
else:
per_worker = (len(self.my_tar_paths) + worker_info.num_workers - 1) // worker_info.num_workers
wid = worker_info.id
curr_paths = self.my_tar_paths[wid * per_worker : (wid + 1) * per_worker]
dctx = zstandard.ZstdDecompressor()
for tar_path in curr_paths:
try:
with open(tar_path, 'rb') as fh:
with dctx.stream_reader(fh) as reader:
with tarfile.open(fileobj=reader, mode='r|') as tar:
for member in tar:
if member.isfile():
f = tar.extractfile(member)
if f:
data = pickle.load(f)
if isinstance(data, dict) and 'vertices' in data:
yield {
'vertices': data['vertices'],
'faces': data['faces'],
'caption': data.get('caption', '无文本描述')
}
except Exception as e:
print(f"❌ 读取错误 {tar_path}: {e}")
continue
def collate_fn(batch):
"""负责将数据组织成 Batch,格式与原始代码保持一致"""
return {
'vertices': [torch.tensor(item['vertices'], dtype=torch.float32) for item in batch],
'faces': [torch.tensor(item['faces'], dtype=torch.long) for item in batch],
'caption': [item['caption'] for item in batch]
}
def get_mesh_dataloader(data_dir, batch_size=4, num_workers=2):
"""统一的 DataLoader 获取接口"""
rank = int(os.environ.get("RANK", 0))
world_size = int(os.environ.get("WORLD_SIZE", 1))
dataset = DyMeshIterableDataset(data_dir, rank=rank, world_size=world_size)
return DataLoader(
dataset,
batch_size=batch_size,
collate_fn=collate_fn,
num_workers=num_workers,
pin_memory=True if torch.cuda.is_available() else False
)