returnn 1.20250630.144055__py3-none-any.whl → 1.20250701.140328__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of returnn might be problematic. Click here for more details.

returnn/PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: returnn
3
- Version: 1.20250630.144055
3
+ Version: 1.20250701.140328
4
4
  Summary: The RWTH extensible training framework for universal recurrent neural networks
5
5
  Home-page: https://github.com/rwth-i6/returnn/
6
6
  Author: Albert Zeyer
@@ -1,2 +1,2 @@
1
- version = '1.20250630.144055'
2
- long_version = '1.20250630.144055+git.f6e5777'
1
+ version = '1.20250701.140328'
2
+ long_version = '1.20250701.140328+git.6646903'
@@ -9,7 +9,7 @@ See https://github.com/rwth-i6/returnn/issues/1519 for initial discussion.
9
9
  Main class is :class:`FileCache`.
10
10
  """
11
11
 
12
- from typing import Any, Collection, Iterable, List, Optional, Tuple, Union
12
+ from typing import Any, Collection, Dict, Iterable, List, Optional, Tuple, Union
13
13
  import errno
14
14
  import os
15
15
  import pathlib
@@ -20,7 +20,7 @@ from dataclasses import dataclass
20
20
  from collections import defaultdict
21
21
  from contextlib import contextmanager
22
22
  import json
23
- from threading import Thread, Event
23
+ from threading import Lock, Thread, Event
24
24
  from returnn.config import Config, get_global_config
25
25
  from .basic import expand_env_vars, LockFile, human_bytes_size
26
26
 
@@ -471,16 +471,20 @@ def _copy_with_prealloc(src: str, dst: str):
471
471
  # Prealloc size + 1, see docstring for why.
472
472
  #
473
473
  # See also `_check_existing_copied_file_maybe_cleanup`.
474
- if os.name == "posix":
474
+ try:
475
475
  os.posix_fallocate(dst_file.fileno(), 0, file_size + 1)
476
- else:
476
+ except AttributeError:
477
+ # posix_fallocate not available (non-Linux unixes), fallback to seek+write
477
478
  dst_file.seek(file_size)
478
479
  dst_file.write(b"\0")
479
480
  dst_file.seek(0)
480
481
  with open(src, "rb") as src_file:
481
- if os.name == "posix":
482
+ try:
482
483
  os.posix_fadvise(src_file.fileno(), 0, file_size, os.POSIX_FADV_SEQUENTIAL)
483
484
  os.posix_fadvise(dst_file.fileno(), 0, file_size, os.POSIX_FADV_SEQUENTIAL)
485
+ except AttributeError:
486
+ # posix_fadvise not available (non-Linux unixes)
487
+ pass
484
488
  shutil.copyfileobj(src_file, dst_file)
485
489
  dst_file.truncate(file_size)
486
490
 
@@ -523,6 +527,8 @@ class _TouchFilesThread(Thread):
523
527
  super().__init__(daemon=True)
524
528
  self.stop = Event()
525
529
  self.files = defaultdict(int) # usage counter
530
+ self.files_lock = Lock() # lock for self.files/self.locks
531
+ self.locks: Dict[str, Lock] = {} # filename -> lock
526
532
  self.interval = interval
527
533
  self.cache_base_dir = cache_base_dir
528
534
  self._is_started = False # careful: `_started` is already a member of the base class
@@ -530,16 +536,17 @@ class _TouchFilesThread(Thread):
530
536
  def run(self):
531
537
  """thread main loop"""
532
538
  while True:
533
- all_files = {} # dict to have order deterministic
534
- for filename in self.files.copy(): # copy dict under GIL to avoid modifications during iteration
535
- all_files[filename] = True
536
- all_files.update({k: True for k in _all_parent_dirs(filename, base_dir=self.cache_base_dir)})
537
- for filename in all_files:
538
- try:
539
- os.utime(filename, None)
540
- except Exception as exc:
541
- print(f"FileCache: failed updating mtime of {filename}: {exc}")
542
- raise
539
+ # locks dict copied under GIL
540
+ locks = self.locks.copy()
541
+ for filename, lock in locks.items():
542
+ with lock:
543
+ if filename not in self.files:
544
+ continue
545
+ try:
546
+ os.utime(filename, None)
547
+ except Exception as exc:
548
+ print(f"FileCache: failed updating mtime of {filename}: {exc}")
549
+ raise
543
550
  if self.stop.wait(self.interval):
544
551
  return
545
552
 
@@ -556,18 +563,26 @@ class _TouchFilesThread(Thread):
556
563
  to_add = [to_add]
557
564
  assert isinstance(to_add, Iterable)
558
565
  self.start_once()
559
- for file in to_add:
560
- self.files[file] += 1
566
+ # we track the parent directories as well and give them their own locks to be
567
+ # able to synchronize their deletion with the touch thread
568
+ files_to_iter = _files_with_parents(to_add, base_dir=self.cache_base_dir)
569
+ with self.files_lock: # to avoid that we end up with duplicate locks
570
+ for file, count in files_to_iter.items():
571
+ self.files[file] += count
572
+ if file not in self.locks:
573
+ self.locks[file] = Lock()
561
574
 
562
575
  def files_remove(self, to_remove: Union[str, Iterable[str]]):
563
576
  """remove"""
564
577
  if isinstance(to_remove, str):
565
578
  to_remove = [to_remove]
566
579
  assert isinstance(to_remove, Iterable)
567
- for filename in to_remove:
568
- self.files[filename] -= 1
569
- if self.files[filename] <= 0:
570
- del self.files[filename]
580
+ for file, count in _files_with_parents(to_remove, base_dir=self.cache_base_dir).items():
581
+ with self.locks[file], self.files_lock:
582
+ self.files[file] -= count
583
+ if self.files[file] <= 0:
584
+ del self.files[file]
585
+ del self.locks[file]
571
586
 
572
587
  @contextmanager
573
588
  def files_added_context(self, files: Collection[str]):
@@ -588,3 +603,12 @@ def _all_parent_dirs(filename: str, *, base_dir: str) -> List[str]:
588
603
  break
589
604
  dirs.append(filename)
590
605
  return dirs
606
+
607
+
608
+ def _files_with_parents(filenames: Iterable[str], *, base_dir: str) -> Dict[str, int]:
609
+ res = defaultdict(int) # dict to have order deterministic
610
+ for fn in filenames:
611
+ res[fn] += 1
612
+ for fn_ in _all_parent_dirs(fn, base_dir=base_dir):
613
+ res[fn_] += 1
614
+ return res
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: returnn
3
- Version: 1.20250630.144055
3
+ Version: 1.20250701.140328
4
4
  Summary: The RWTH extensible training framework for universal recurrent neural networks
5
5
  Home-page: https://github.com/rwth-i6/returnn/
6
6
  Author: Albert Zeyer
@@ -1,9 +1,9 @@
1
- returnn/PKG-INFO,sha256=oArSv5bUp8K8GvxXohm9s9wT01agfHCKCCPkOpIwam4,5215
1
+ returnn/PKG-INFO,sha256=RByOzAa8sFb4gdGsaWiRUEOlZq3X9qqn4MEF0ziNPNc,5215
2
2
  returnn/__init__.py,sha256=biBtRsM0WZ406vShaeH-9WFoqJ8XwTbn6g0EeFJ7l8E,1012
3
3
  returnn/__main__.py,sha256=lHyZcu_0yc9f7Vf_Kfdy9PmeU0T76XVXnpalHi5WKro,31740
4
4
  returnn/__old_mod_loader__.py,sha256=nvsNY-xELdS_IPNkv66Q9Rmvg4dbGW0-EBRDcCmctos,7654
5
5
  returnn/__setup__.py,sha256=22kQn2fh11iPM0hLb2Fy5sLmoU1JGvmDxXRYuRgQkwU,4659
6
- returnn/_setup_info_generated.py,sha256=K1zKiBQqCegRMxogGE8FpdqD_P4p13jMYXh480Gs5aY,77
6
+ returnn/_setup_info_generated.py,sha256=FycWE5HycEgzbwEzgqhdpFdUBY_4Kg7Rlg43mZCjiBs,77
7
7
  returnn/config.py,sha256=3tmKhB6FnQZaNdtcYsiB61JnEY--iZ2qmJ4yq0b6tE0,29140
8
8
  returnn/forward_iface.py,sha256=A_OJiaXsX4MlXQRzST86ylyxSUZbC402PQL1REcqHjM,911
9
9
  returnn/learning_rate_control.py,sha256=ZvWryAn_tv9DhV8sh1LV3eE34Yltl3On3mYZAG4hR9s,34684
@@ -238,7 +238,7 @@ returnn/util/better_exchook.py,sha256=39yvRecluDgYhViwSkaQ8crJ_cBWI63KeEGuK4RKe5
238
238
  returnn/util/bpe.py,sha256=LWFhICZsEOnMwNws0lybPNzKRX6rSr8yKCvP65vjl9Y,19656
239
239
  returnn/util/debug.py,sha256=wuRzdg9zB84WWCGyTjmRR_zYypu8gXxlc0nZ6si9OC8,28224
240
240
  returnn/util/debug_helpers.py,sha256=0EINLK4uLtoSt5_kHs1M2NIFpMd0S7i4c4rx90U4fJk,2914
241
- returnn/util/file_cache.py,sha256=tXM2Leos8fOc1tzmQbGSLYgzQoKAw1klCw-k9TwoAno,26453
241
+ returnn/util/file_cache.py,sha256=15p0daE4KmzO5OvkhDr9cA_zJNbJrX98mnL-2fECtmM,27575
242
242
  returnn/util/fsa.py,sha256=k2lJ8tyf_g44Xk1EPVLwDwpP4spoMTqIigDVOWocQHY,59177
243
243
  returnn/util/literal_py_to_pickle.py,sha256=3dnjWPeeiDT2xp4bRDgIf9yddx7b1AG7mOKEn_jiSl8,2173
244
244
  returnn/util/lru_cache.py,sha256=7Q5H3a8b07E8e1iB7PA9jCpRnxMJZOFS2KO07cy0gqk,11446
@@ -253,8 +253,8 @@ returnn/util/sig_proc.py,sha256=Tjz0VOAVyqu2qDCF5HZ1JjALjcFsHcNkcd96WgZeKfE,7265
253
253
  returnn/util/task_system.py,sha256=y4sMVXQ25Qd2z0rx03uOlXlkE-jbCYC1Sjfn-XlraVU,26003
254
254
  returnn/util/train_proc_manager.py,sha256=Pjht28k6uz6BNQ47uW6Gf880iyq5q4wx7P_K2tmoAM8,3266
255
255
  returnn/util/watch_memory.py,sha256=BR5P2kvBN6UI81cE0_1WAA6Hd1SByLbBaiDxvLhPOew,4213
256
- returnn-1.20250630.144055.dist-info/LICENSE,sha256=ywBD_U2aD4vpuoIgNAsjIGBYydl0tVKll3De0Z8s77c,11041
257
- returnn-1.20250630.144055.dist-info/METADATA,sha256=oArSv5bUp8K8GvxXohm9s9wT01agfHCKCCPkOpIwam4,5215
258
- returnn-1.20250630.144055.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
259
- returnn-1.20250630.144055.dist-info/top_level.txt,sha256=Lsn4WZc5Pbfk0-xDQOgnFCxOoqxL4CyeM3N1TFbJncw,8
260
- returnn-1.20250630.144055.dist-info/RECORD,,
256
+ returnn-1.20250701.140328.dist-info/LICENSE,sha256=ywBD_U2aD4vpuoIgNAsjIGBYydl0tVKll3De0Z8s77c,11041
257
+ returnn-1.20250701.140328.dist-info/METADATA,sha256=RByOzAa8sFb4gdGsaWiRUEOlZq3X9qqn4MEF0ziNPNc,5215
258
+ returnn-1.20250701.140328.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
259
+ returnn-1.20250701.140328.dist-info/top_level.txt,sha256=Lsn4WZc5Pbfk0-xDQOgnFCxOoqxL4CyeM3N1TFbJncw,8
260
+ returnn-1.20250701.140328.dist-info/RECORD,,