Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
585f375
Fix s3pytorch force path style boolean option.
dpsi Jan 14, 2026
7078286
Refactor S3 pytorch implementation.
dpsi Jan 19, 2026
add6b26
feat: Add multi-library S3 storage support (minio, s3dlio, s3torch)
russfellows Feb 19, 2026
9354ae7
refactor: convert direct imports to lazy imports in profiler_factory …
izzet Feb 27, 2026
57148a1
feat: add native AIStore storage backend (#321)
gaikwadabhishek Mar 2, 2026
ea53bcf
fix(counters): train phase was not evaluated (#328)
enakta Mar 13, 2026
8b280cb
refactor(generators): unify generators to work with any storage backe…
enakta Mar 18, 2026
14561b8
feat: object storage integration work-in-progress (multi-library S3, …
russfellows Mar 18, 2026
f0c3743
Merge remote-tracking branch 'upstream/main' into feature/object-stor…
russfellows Mar 18, 2026
bc3b576
refactor: consolidate S3 storage, fix test output dir, centralise env…
russfellows Mar 19, 2026
a207bcb
Merge pull request #1 from russfellows/feature/object-storage-integra…
russfellows Mar 19, 2026
56b45da
feat: add parallel S3 iterable readers and parquet byte-range support…
russfellows Mar 19, 2026
4d5703c
Merge pull request #2 from russfellows/feature/parquet-readers-and-it…
russfellows Mar 19, 2026
8b294dc
feat: add DIRECT_FS storage type and route it in storage_factory
russfellows Mar 20, 2026
652db18
feat: add PT_OBJ_SAVE checkpoint type for minio/s3dlio object store b…
russfellows Mar 20, 2026
3f37071
Merge pull request #3 from russfellows/feat/obj-store-checkpointing
russfellows Mar 20, 2026
7f54fa4
feat: add multi-library S3 iterable readers with strict isolation and…
russfellows Mar 21, 2026
dff04ce
refactor: collapse S3 iterable readers into thin subclasses via _S3It…
russfellows Mar 21, 2026
97b4570
fix: make all 3 storage libraries consistent in _s3_iterable_mixin an…
russfellows Mar 21, 2026
816ec88
feat: add ParquetReader for local/network filesystems; fix factory ro…
russfellows Mar 21, 2026
659faa2
refactor: AIStore cleanup — remove stale restrictions, debug prints, …
russfellows Mar 21, 2026
0ca32e8
chore: remove orphaned s3_storage_dpsi.py
russfellows Mar 21, 2026
6ce2df8
chore: comment out DEBUG print statements in ObjStoreLibStorage
russfellows Mar 21, 2026
e06c54f
storage: convert commented debug prints to logging.debug() in obj_sto…
russfellows Mar 21, 2026
8ad890f
Merge pull request #4 from russfellows/feat/multi-lib-storage-readers…
russfellows Mar 21, 2026
635d083
feat: multi-library object-store checkpointing (s3dlio / minio / s3to…
russfellows Mar 25, 2026
ca08e29
Merge pull request #5 from russfellows/bugs/checkpoint-fixes
russfellows Mar 25, 2026
3c25dbb
merge: resolve conflicts with mlcommons/DLIO_local_changes main
russfellows Mar 26, 2026
dc49693
feat: full object storage support for all formats — generators, reade…
russfellows Mar 27, 2026
7a79779
Merge pull request #6 from russfellows/feat/fix-object-gen-and-readers
russfellows Mar 27, 2026
b576bc0
chore: remove backup file from docs
russfellows Mar 27, 2026
6442b35
fix: add dgen-py>=0.2.0 as required dependency
russfellows Mar 27, 2026
70f2cef
fix: make dgen-py a soft dependency with numpy fallback
russfellows Mar 27, 2026
f233c13
ci: drop Python 3.9 and 3.10 from matrix, require 3.11+
russfellows Mar 27, 2026
1554eba
ci: drop Python 3.9/3.10, add dgen-py to requirements-test.txt
russfellows Mar 27, 2026
4ba09cc
fix: soften dgen-py hard fail in config.py, fix CI cache key to inclu…
russfellows Mar 27, 2026
df3bbd8
fix: reduce parallelism in failing tests due to over subscription, fr…
russfellows Mar 27, 2026
a65ca5f
Stabilize DFTracer CI and checkpoint tests on Python 3.12
russfellows Mar 27, 2026
5db4f2b
CI: align dgen-py usage with 0.2.2 and Python 3.11+
russfellows Mar 27, 2026
a4760f9
Tests: fix output glob path in checkpoint benchmark verification
russfellows Mar 28, 2026
56584e0
Tests: harden output-path checks and checkpoint count arithmetic
russfellows Mar 28, 2026
b3bfe5b
Tests: suppress Python 3.12 multiprocessing fork deprecation noise
russfellows Mar 28, 2026
bd64c3c
Tests: keep fork warnings visible and fix mocked S3 storage library c…
russfellows Mar 28, 2026
3435b39
Tests: make object-storage coverage minimal by default
russfellows Mar 28, 2026
1c7fe33
Tests: gate object-storage suites behind opt-in flag
russfellows Mar 28, 2026
79e6dc5
Skip object storage tests cleanly
russfellows Mar 28, 2026
5330734
Gate object storage CI steps
russfellows Mar 28, 2026
1087fb3
docs: add I/O issues analysis and executive summary (2026-03-28)
russfellows Mar 28, 2026
e1b17d6
ci: remove S3TorchConnector tests from CI workflow
russfellows Apr 9, 2026
b1696e1
fix: minio connection pool, s3torchconnector bool, obj_store fixes
russfellows Apr 10, 2026
81f6de1
Merge remote-tracking branch 'russfellows/main' into dev
russfellows Apr 10, 2026
0a1b3c5
Merge pull request #7 from russfellows/dev
russfellows Apr 10, 2026
ea13c3a
Add parquet configuration options to ConfigArguments and LoadConfig (#9)
wolfgang-desalvador Apr 9, 2026
f58903c
Optimize Parquet generation: pre-generate full table, zero-copy slice…
wolfgang-desalvador Apr 10, 2026
7927665
Add uv support: [project] table in pyproject.toml + uv.lock
russfellows Apr 10, 2026
ee32845
chore: ignore coderag index and fastembed cache directories
russfellows Apr 12, 2026
d5a1847
test: Batch E — test infra hardening, disable dftracer, spawn MP, fix…
russfellows Apr 13, 2026
dd146e1
fix(readers+gen): PR-2/3 — local-FS reader parity + JPEG/PNG fast gen…
russfellows Apr 12, 2026
1a29d52
fix(config): PR-1/4/5 — iterative sampler bug, multiprocessing_contex…
russfellows Apr 12, 2026
d7ccd8d
test: fix test_npy_reader_compatibility for LocalFSIterableMixin design
russfellows Apr 13, 2026
100023f
Merge pull request #8 from russfellows/fix/reader-parity-and-generato…
russfellows Apr 13, 2026
fb72852
Merge pull request #9 from russfellows/fix/config-correctness-and-aut…
russfellows Apr 13, 2026
d9f175b
test: Batch E — test infra hardening, disable dftracer, spawn MP, fix…
russfellows Apr 13, 2026
d8414bf
Merge pull request #10 from russfellows/fix/test-infra-hardening-pr
russfellows Apr 13, 2026
6200446
test: add PR verification benchmarks and report (April 12, 2026)
russfellows Apr 13, 2026
67c9c6d
Merge pull request #11 from russfellows/feat/pr-verification-tests-ap…
russfellows Apr 13, 2026
55df654
fix: parallel generation, storage env vars, MPI topology, settle guar…
russfellows Apr 13, 2026
7d3348f
Merge pull request #12 from russfellows/fix/issues-9-10-11-12-13-6b
russfellows Apr 13, 2026
e2d612f
fix: cap auto-sized thread count in tests and CI (DLIO_MAX_AUTO_THREADS)
russfellows Apr 13, 2026
c031c3f
Merge pull request #13 from russfellows/fix/ci-thread-cap-and-test-st…
russfellows Apr 13, 2026
4767619
Merge branch 'main' into upstream-pr/all-fixes-apr2026
russfellows Apr 13, 2026
c21a37c
chore: remove uv.lock, internal docs, and bench scripts from upstream PR
russfellows Apr 13, 2026
bdd7901
chore: lock Python to 3.12 only (>=3.12,<3.13)
russfellows Apr 13, 2026
af94edf
fix: add pydftracer to setup.py test deps for Preflight C extension c…
russfellows Apr 13, 2026
73d87c1
fix: restore pydftracer to core_deps (was removed in earlier commit, …
russfellows Apr 13, 2026
8c66d92
fix: add pydftracer to pyproject.toml dependencies (pip ignores setup…
russfellows Apr 13, 2026
9f9c800
fix: add dftracer>=2.0.1 to pyproject.toml test extras (provides C ex…
russfellows Apr 13, 2026
9103266
fix: add pyproject.toml to CI cache key to prevent stale venv reuse
russfellows Apr 13, 2026
2f61e04
fix: drop incomplete last batch in FormatReader.next() to match drop_…
russfellows Apr 13, 2026
b8ec143
fix: pin read_threads=1 in test_ai_logging_train to avoid per-thread …
russfellows Apr 13, 2026
6f39d83
fix: restore dftracer loading — conditional import from DFTRACER_ENAB…
russfellows Apr 13, 2026
5824171
fix: add missing global declarations for dftracer in __init__ and fin…
russfellows Apr 13, 2026
6ceb009
ci: remove test_ai_logging step — dftracer integration tests not needed
russfellows Apr 13, 2026
80da1ad
ci: replace push/PR trigger with fast CI suite; keep integration test…
russfellows Apr 15, 2026
7da0b04
ci: add pyarrow to requirements-test.txt for via-reqs leg
russfellows Apr 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions .github/workflows/fast-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: Fast CI

# Run on every push / PR — completes in < 10 minutes per matrix leg.
# Covers: preflight import checks, enumerations, utilities, config logic,
# factories, data generators, reader compat, MPI smoke, and a small
# end-to-end generate+train loop.
#
# Runs under THREE install methods:
# via-uv : uv venv + uv pip install .[test] (preferred going forward)
# via-setup : python -m venv + pip install .[test] (traditional editable)
# via-reqs : python -m venv + pip install -r requirements-test.txt
# + PYTHONPATH=$(pwd)
#
# For the full integration test suite see integration.yml (manual via workflow_dispatch).

on:
push:
branches: ["**"]
pull_request:
branches: ["**"]

jobs:
fast-ci:
strategy:
fail-fast: false
matrix:
install_method: ["via-uv", "via-setup", "via-reqs"]
name: fast-ci (${{ matrix.install_method }})
runs-on: ubuntu-latest
timeout-minutes: 20

env:
OMPI_ALLOW_RUN_AS_ROOT: "1"
OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: "1"
DLIO_OBJECT_STORAGE_TESTS: "0"
DLIO_MAX_AUTO_THREADS: "2"
DFTRACER_ENABLE: "1"
RDMAV_FORK_SAFE: "1"
VENV_PATH: "/home/runner/work/.venv/${{ matrix.install_method }}"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: "pip"

- name: Install MPI
run: |
sudo apt-get update -q
sudo apt-get install -y --no-install-recommends \
openmpi-bin libopenmpi-dev

- name: Install uv
run: pip install uv

- name: Install DLIO via uv (via-uv)
if: matrix.install_method == 'via-uv'
run: |
uv venv "${VENV_PATH}"
source "${VENV_PATH}/bin/activate"
uv pip install ".[test]"

- name: Install DLIO via setup.py (via-setup)
if: matrix.install_method == 'via-setup'
run: |
python -m venv "${VENV_PATH}"
source "${VENV_PATH}/bin/activate"
pip install --upgrade pip
pip install ".[test]"

- name: Install DLIO via requirements.txt (via-reqs)
if: matrix.install_method == 'via-reqs'
run: |
python -m venv "${VENV_PATH}"
source "${VENV_PATH}/bin/activate"
pip install --upgrade pip
pip install -r requirements-test.txt
# dlio_benchmark is not installed as a package in this path —
# add the repo root to PYTHONPATH so imports resolve, same as
# the old ci.yml did.
echo "PYTHONPATH=$(pwd):${PYTHONPATH}" >> "${GITHUB_ENV}"

- name: Activate venv for remaining steps
run: echo "${VENV_PATH}/bin" >> "${GITHUB_PATH}"

- name: Run fast CI tests
# Exit code 134 = SIGABRT from TF+OpenMPI process teardown after all
# tests have already passed. We tolerate it by inspecting the JUnit
# XML rather than trusting mpirun's exit code.
run: |
python -m pytest tests/test_fast_ci.py \
--tb=short -v \
--junitxml=fast-ci-results-${{ matrix.install_method }}.xml \
|| code=$?; \
if [ "${code:-0}" -eq 134 ]; then \
echo "Exit 134 (SIGABRT teardown) — checking results XML..."; \
python -c "
import xml.etree.ElementTree as ET, sys
tree = ET.parse('fast-ci-results-${{ matrix.install_method }}.xml')
suite = tree.getroot().find('testsuite') or tree.getroot()
failures = int(suite.get('failures', 0)) + int(suite.get('errors', 0))
tests = int(suite.get('tests', 0))
print(f'Tests: {tests} Failures/Errors: {failures}')
sys.exit(1 if failures > 0 else 0)
"; \
elif [ "${code:-0}" -ne 0 ]; then \
exit "${code:-0}"; \
fi

- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: fast-ci-results-${{ matrix.install_method }}
path: fast-ci-results-${{ matrix.install_method }}.xml

19 changes: 6 additions & 13 deletions .github/workflows/ci.yml → .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Build and Test
name: Integration Tests (Manual)

# Full 21-suite integration run. Trigger manually via the GitHub Actions UI.
# For every-commit CI see fast-ci.yml.
on:
pull_request:
branches: [main, dev]
push:
workflow_dispatch:

jobs:
build-and-test:
Expand All @@ -23,6 +23,7 @@ jobs:
DFTRACER_ENABLE: 1
DFTRACER_LOG_LEVEL: "INFO"
DLIO_EXEC: ${{ matrix.venv == 'via-setup' && 'dlio_benchmark' || 'python dlio_benchmark/main.py' }}
DLIO_MAX_AUTO_THREADS: "2"
DLIO_OBJECT_STORAGE_TESTS: "0"
GOTCHA_DEBUG: 1
OMPI_ALLOW_RUN_AS_ROOT: 1
Expand Down Expand Up @@ -57,7 +58,7 @@ jobs:
uses: actions/cache@v3
with:
path: ${{ env.VENV_PATH }}
key: ${{ matrix.venv }}-gcc${{ matrix.gcc }}-python${{ matrix.python }}-${{ hashFiles('requirements.txt', 'requirements-test.txt', 'setup.py') }}
key: ${{ matrix.venv }}-gcc${{ matrix.gcc }}-python${{ matrix.python }}-${{ hashFiles('requirements.txt', 'requirements-test.txt', 'setup.py', 'pyproject.toml') }}
- name: Install system dependencies
run: |
sudo apt update
Expand Down Expand Up @@ -122,14 +123,6 @@ jobs:

print("Preflight import check passed")
PY
- name: test_ai_logging
env:
DFTRACER_INC_METADATA: 1
DFTRACER_TRACE_COMPRESSION: 0
run: |
source ${VENV_PATH}/bin/activate
pytest tests/dlio_ai_logging_test.py -n 4 -v
rm -rf outputs
- name: test_dataset_dimension_gen_data
run: |
source ${VENV_PATH}/bin/activate
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ stuff/
*.un~
hydra_log/

# coderag local code-intelligence index (generated by coderag index .)
.coderag/

# fastembed model download cache (generated by coderag on first run)
.fastembed_cache/


# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
2 changes: 1 addition & 1 deletion dlio_benchmark/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# boto3/botocore are banned — block immediately on dlio_benchmark import.
try:
from mlpstorage.ban_boto3 import install as _ban_boto3
from mlpstorage_py.ban_boto3 import install as _ban_boto3
_ban_boto3()
except ImportError:
pass # mlpstorage not installed in this env; skip gracefully
2 changes: 1 addition & 1 deletion dlio_benchmark/checkpointing/pytorch_checkpointing.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def _get_streaming(self):

if cache_key not in self._streaming_cache:
try:
from mlpstorage.checkpointing import StreamingCheckpointing as _SC
from mlpstorage_py.checkpointing import StreamingCheckpointing as _SC
except ImportError:
from dlio_benchmark.checkpointing.simple_streaming_checkpointing import (
SimpleStreamingCheckpointing as _SC,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def __init__(self):

# Build StreamingCheckpointing once; reused for all save/load calls.
try:
from mlpstorage.checkpointing import StreamingCheckpointing as _SC
from mlpstorage_py.checkpointing import StreamingCheckpointing as _SC
except ImportError as exc:
raise ImportError(
"Object-store checkpointing requires mlpstorage. "
Expand Down
62 changes: 44 additions & 18 deletions dlio_benchmark/data_generator/data_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from abc import ABC, abstractmethod
import io
from concurrent.futures import ThreadPoolExecutor

from dlio_benchmark.utils.config import ConfigArguments
from dlio_benchmark.storage.storage_factory import StorageFactory
Expand All @@ -36,6 +37,9 @@ class DataGenerator(ABC):

def __init__(self):
self._args = ConfigArguments.get_instance()
# Issue 6b note: derive_configurations() here runs the early (no file list) path.
# validate() is NOT called here — it is called in main.py after the file list walk.
# This is intentional: validate() checks file counts which aren't known until walk.
self._args.derive_configurations()
self._dimension = self._args.dimension
self._dimension_stdev = self._args.dimension_stdev
Expand Down Expand Up @@ -99,6 +103,7 @@ def _generate_files(self, write_fn, label: str = "Data") -> None:
- Dimension extraction (scalar / list branch).
- BytesIO abstraction for object storage.
- ``storage.put_data()`` after each file when not on local FS.
- Parallel file writes via ``ThreadPoolExecutor`` when ``write_threads > 1``.

**write_fn signature**::

Expand All @@ -110,14 +115,13 @@ def _generate_files(self, write_fn, label: str = "Data") -> None:
- ``i`` : global file index (unique per file across all ranks)
- ``dim_`` : raw dimension from ``get_dimension()`` (list or int)
- ``dim1, dim2`` : extracted scalar first/second dimensions
- ``file_seed`` : reproducible per-file seed derived from ``rng`` via
``rng.integers(0, 2**63)``. Not the arithmetic
``BASE_SEED + i`` — seeds are well-spread across
the full int64 space, eliminating adjacent-seed
correlations. The sequence is deterministic.
- ``rng`` : ``np.random.Generator`` seeded with
``BASE_SEED + my_rank`` (for any additional
per-rank stochastic ops inside write_fn)
- ``file_seed`` : reproducible per-file seed (int64). Each worker
creates its own ``np.random.default_rng(file_seed)``
so that: (a) no shared mutable state crosses thread
boundaries, and (b) the same config always generates
identical files regardless of ``write_threads``.
- ``rng`` : ``np.random.Generator`` seeded from ``file_seed`` —
a fresh instance per file, safe for concurrent use.
- ``out_path_spec``: fully-resolved path string
- ``is_local`` : ``True`` for local filesystem, ``False`` for object store
- ``output`` : ``out_path_spec`` when ``is_local``,
Expand All @@ -126,34 +130,56 @@ def _generate_files(self, write_fn, label: str = "Data") -> None:
After ``write_fn`` returns, if ``not is_local``, the template calls::

storage.put_data(out_path_spec, output.getvalue())

**Parallel semantics** (Issue 10):

Seeds are pre-derived sequentially in the main thread so that
determinism is preserved: ``same master seed → same per-file seeds →
identical files`` regardless of ``write_threads`` value.
Worker threads each receive a pre-computed seed and create their own
independent ``np.random.Generator`` — no shared RNG state.
"""
# Rank-unique seed for get_dimension() global random state.
# Each rank gets the same base seed offset by its rank number, ensuring
# dimensions are reproducible per-rank but different across ranks.
np.random.seed(self.BASE_SEED + self.my_rank)
rng = np.random.default_rng(seed=self.BASE_SEED + self.my_rank)
dim = self.get_dimension(self.total_files_to_generate)
is_local = self.storage.islocalfs()

# Phase 1: Pre-derive all (index, dims, seed, path) in the main thread.
# rng.integers() calls MUST happen in order to preserve the deterministic
# sequence; workers receive pre-computed seeds and never touch this rng.
jobs = []
for i in dlp_base.iter(range(self.my_rank,
int(self.total_files_to_generate),
self.comm_size)):
dim_, dim1, dim2 = self._extract_dims(dim, i)
out_path_spec = self.storage.get_uri(self._file_list[i])
progress(i + 1, self.total_files_to_generate, f"Generating {label}")
output = out_path_spec if is_local else io.BytesIO()
# Derive file seed from the flowing RNG — not arithmetic (BASE_SEED + i).
# This produces well-spread, non-adjacent seeds without "resetting" the
# RNG between files. The sequence is deterministic: same master seed →
# same derived sequence → same files on every run.
file_seed = int(rng.integers(0, 2**63))
jobs.append((i, dim_, dim1, dim2, file_seed, out_path_spec))

write_fn(i, dim_, dim1, dim2, file_seed, rng,
# Phase 2: Execute writes, optionally in parallel.
# Each worker creates a fresh rng from its pre-derived file_seed so
# there is no shared mutable state between threads.
def _write_one(job):
i, dim_, dim1, dim2, file_seed, out_path_spec = job
progress(i + 1, self.total_files_to_generate, f"Generating {label}")
output = out_path_spec if is_local else io.BytesIO()
worker_rng = np.random.default_rng(seed=file_seed)
write_fn(i, dim_, dim1, dim2, file_seed, worker_rng,
out_path_spec, is_local, output)

if not is_local:
self.storage.put_data(out_path_spec, output.getvalue())

write_threads = getattr(self._args, 'write_threads', 1)
n_workers = max(1, min(write_threads, len(jobs))) if jobs else 1

if n_workers == 1 or len(jobs) <= 1:
for job in jobs:
_write_one(job)
else:
with ThreadPoolExecutor(max_workers=n_workers) as pool:
list(pool.map(_write_one, jobs))

np.random.seed() # Reset global seed to avoid leaking state

def get_dimension(self, num_samples=1):
Expand Down
25 changes: 23 additions & 2 deletions dlio_benchmark/data_generator/jpeg_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import PIL.Image as im

from dlio_benchmark.data_generator.data_generator import DataGenerator
from dlio_benchmark.common.enumerations import DataLoaderType
from dlio_benchmark.utils.utility import progress, utcnow, gen_random_tensor
from dlio_benchmark.utils.utility import Profile
from dlio_benchmark.common.constants import MODULE_DATA_GENERATOR
Expand All @@ -35,11 +36,20 @@ def generate(self):
"""
Generator for creating data in JPEG format of 3d dataset.
Uses the base-class template for seeding, BytesIO, and put_data.

Fast path (non-DALI): writes raw random bytes — no PIL encode.
PIL encode costs ~30 ms/file and the bytes are never decoded by
any benchmark reader path. Skipping it gives a 1000-4000x speedup
for large synthetic datasets.

DALI path: keeps the full PIL encode because fn.decoders.image()
requires a valid JPEG bitstream.
"""
super().generate()
my_rank = self.my_rank
total = self.total_files_to_generate
logger = self.logger
use_fast_path = (self._args.data_loader != DataLoaderType.NATIVE_DALI)

def _write(i, dim_, dim1, dim2, file_seed, rng,
out_path_spec, is_local, output):
Expand All @@ -48,9 +58,20 @@ def _write(i, dim_, dim1, dim2, file_seed, rng,
records = np.clip(records, 0, 255).astype(np.uint8)
if my_rank == 0:
logger.debug(f"{utcnow()} Dimension of images: {dim1} x {dim2}")
img = im.fromarray(records)
if my_rank == 0 and i % 100 == 0:
logger.info(f"Generated file {i}/{total}")
img.save(output, format='JPEG', bits=8)
if use_fast_path:
# Write raw bytes — no PIL encode. Benchmark readers only
# measure byte count, never decode the content.
if is_local:
with open(out_path_spec, 'wb') as f:
f.write(records.tobytes())
else:
output.write(records.tobytes())
else:
# Full PIL encode for native_dali: fn.decoders.image() needs
# a valid JPEG bitstream.
img = im.fromarray(records)
img.save(output, format='JPEG', bits=8)

self._generate_files(_write, "JPEG Data")
Loading
Loading