loaderx 0.2.1__tar.gz → 0.3.0__tar.gz
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.
- {loaderx-0.2.1 → loaderx-0.3.0}/PKG-INFO +3 -3
- {loaderx-0.2.1 → loaderx-0.3.0}/README.md +1 -1
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx/__init__.py +1 -1
- loaderx-0.3.0/loaderx/_sampler.py +69 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx/dataloader.py +2 -2
- loaderx-0.3.0/loaderx/lib/libsampler.so +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx.egg-info/PKG-INFO +3 -3
- {loaderx-0.2.1 → loaderx-0.3.0}/pyproject.toml +1 -1
- loaderx-0.2.1/loaderx/_sampler.py +0 -114
- loaderx-0.2.1/loaderx/lib/libsampler.so +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/LICENSE +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx/dataset.py +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx/utils.py +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx.egg-info/SOURCES.txt +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx.egg-info/dependency_links.txt +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx.egg-info/requires.txt +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/loaderx.egg-info/top_level.txt +0 -0
- {loaderx-0.2.1 → loaderx-0.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: loaderx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A record-based data runtime, focused on delivering extreme throughput and low latency
|
|
5
5
|
Author-email: Ben0i0d <ben0i0d@foxmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -34,7 +34,7 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
34
34
|
Classifier: Intended Audience :: Developers
|
|
35
35
|
Classifier: License :: OSI Approved :: MIT License
|
|
36
36
|
Classifier: Programming Language :: Python :: 3
|
|
37
|
-
Requires-Python:
|
|
37
|
+
Requires-Python: ==3.13
|
|
38
38
|
Description-Content-Type: text/markdown
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Dist: numpy
|
|
@@ -45,7 +45,7 @@ Dynamic: license-file
|
|
|
45
45
|
# loaderx
|
|
46
46
|
A record-based data runtime, focused on delivering extreme throughput and low latency
|
|
47
47
|
|
|
48
|
-
**
|
|
48
|
+
**Only Python3.13_Linux_amd64**
|
|
49
49
|
|
|
50
50
|
## Sampler
|
|
51
51
|
a high-performance sampler implemented in Zig
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# loaderx
|
|
2
2
|
A record-based data runtime, focused on delivering extreme throughput and low latency
|
|
3
3
|
|
|
4
|
-
**
|
|
4
|
+
**Only Python3.13_Linux_amd64**
|
|
5
5
|
|
|
6
6
|
## Sampler
|
|
7
7
|
a high-performance sampler implemented in Zig
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import time
|
|
3
|
+
import ctypes
|
|
4
|
+
import numpy as np
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
from lib import libsampler
|
|
8
|
+
|
|
9
|
+
class Sampler:
|
|
10
|
+
class Mode:
|
|
11
|
+
SEQUENTIAL = 0
|
|
12
|
+
IID = 1
|
|
13
|
+
|
|
14
|
+
def __init__(self, length: int, batch_size: int, mode: int, seed: int = 42):
|
|
15
|
+
# sampler
|
|
16
|
+
self.sampler = libsampler.Sampler.init(length, batch_size, mode, seed)
|
|
17
|
+
# indices
|
|
18
|
+
self.indices = np.zeros(batch_size, dtype=np.uint64)
|
|
19
|
+
|
|
20
|
+
# step
|
|
21
|
+
def next(self):
|
|
22
|
+
self.sampler.next(self.indices)
|
|
23
|
+
|
|
24
|
+
# iterator
|
|
25
|
+
def __iter__(self):
|
|
26
|
+
return self
|
|
27
|
+
def __next__(self):
|
|
28
|
+
self.next()
|
|
29
|
+
return self.indices
|
|
30
|
+
|
|
31
|
+
def run():
|
|
32
|
+
from itertools import islice
|
|
33
|
+
length = 10
|
|
34
|
+
batch_size = 4
|
|
35
|
+
n_steps = 5
|
|
36
|
+
|
|
37
|
+
print("=== Sampler SEQUENTIAL ===")
|
|
38
|
+
sampler = Sampler(length, batch_size, Sampler.Mode.SEQUENTIAL)
|
|
39
|
+
for indices in islice(sampler, n_steps):
|
|
40
|
+
print(indices)
|
|
41
|
+
|
|
42
|
+
print("=== Sampler IID ===")
|
|
43
|
+
sampler = Sampler(length, batch_size, Sampler.Mode.IID)
|
|
44
|
+
for indices in islice(sampler, n_steps):
|
|
45
|
+
print(indices)
|
|
46
|
+
|
|
47
|
+
# Benchmark, zig-sampler speeder 2.2x
|
|
48
|
+
def bench():
|
|
49
|
+
length = 1_000_000
|
|
50
|
+
batch_size = 8192
|
|
51
|
+
n_steps = 10_000
|
|
52
|
+
|
|
53
|
+
print("=== NumPy IID ===")
|
|
54
|
+
t0 = time.time()
|
|
55
|
+
batch = np.zeros(batch_size, dtype=np.uint64)
|
|
56
|
+
for _ in range(n_steps):
|
|
57
|
+
batch[:] = np.random.randint(0, length, size=batch_size, dtype=np.uint64)
|
|
58
|
+
print(f"{(time.time() - t0)*1000:.2f} ms")
|
|
59
|
+
|
|
60
|
+
print("=== Sampler IID ===")
|
|
61
|
+
t0 = time.time()
|
|
62
|
+
sampler = Sampler(length, batch_size, Sampler.Mode.IID)
|
|
63
|
+
for _ in range(n_steps):
|
|
64
|
+
sampler.next()
|
|
65
|
+
print(f"{(time.time() - t0)*1000:.2f} ms")
|
|
66
|
+
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
run()
|
|
69
|
+
bench()
|
|
@@ -47,8 +47,8 @@ class DataLoader:
|
|
|
47
47
|
Sample indices from the dataset and put them into the index queue.
|
|
48
48
|
"""
|
|
49
49
|
while not self.stop_signal.is_set():
|
|
50
|
-
self.sampler.next()
|
|
51
|
-
self.indices.put(self.sampler.
|
|
50
|
+
self.sampler.next()
|
|
51
|
+
self.indices.put(self.sampler.indices.copy())
|
|
52
52
|
|
|
53
53
|
def _prefetch(self, transform):
|
|
54
54
|
"""
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: loaderx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A record-based data runtime, focused on delivering extreme throughput and low latency
|
|
5
5
|
Author-email: Ben0i0d <ben0i0d@foxmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -34,7 +34,7 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
34
34
|
Classifier: Intended Audience :: Developers
|
|
35
35
|
Classifier: License :: OSI Approved :: MIT License
|
|
36
36
|
Classifier: Programming Language :: Python :: 3
|
|
37
|
-
Requires-Python:
|
|
37
|
+
Requires-Python: ==3.13
|
|
38
38
|
Description-Content-Type: text/markdown
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Dist: numpy
|
|
@@ -45,7 +45,7 @@ Dynamic: license-file
|
|
|
45
45
|
# loaderx
|
|
46
46
|
A record-based data runtime, focused on delivering extreme throughput and low latency
|
|
47
47
|
|
|
48
|
-
**
|
|
48
|
+
**Only Python3.13_Linux_amd64**
|
|
49
49
|
|
|
50
50
|
## Sampler
|
|
51
51
|
a high-performance sampler implemented in Zig
|
|
@@ -7,7 +7,7 @@ name = "loaderx"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = "A record-based data runtime, focused on delivering extreme throughput and low latency"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = "
|
|
10
|
+
requires-python = "==3.13"
|
|
11
11
|
authors = [
|
|
12
12
|
{name = "Ben0i0d", email = "ben0i0d@foxmail.com"},
|
|
13
13
|
]
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import time
|
|
3
|
-
import ctypes
|
|
4
|
-
import numpy as np
|
|
5
|
-
from typing import Union
|
|
6
|
-
|
|
7
|
-
class Sampler:
|
|
8
|
-
|
|
9
|
-
class Mode:
|
|
10
|
-
SEQUENTIAL = 0
|
|
11
|
-
IID = 1
|
|
12
|
-
|
|
13
|
-
# lazy import
|
|
14
|
-
_lib = None
|
|
15
|
-
@classmethod
|
|
16
|
-
def _load_lib(cls):
|
|
17
|
-
if cls._lib is None:
|
|
18
|
-
# linux/windows/macos
|
|
19
|
-
names = ['lib/libsampler.so', 'lib/sampler.dll', 'lib/libsampler.dylib']
|
|
20
|
-
lib_paths = [os.path.join(os.path.dirname(__file__), name) for name in names]
|
|
21
|
-
|
|
22
|
-
for path in lib_paths:
|
|
23
|
-
if os.path.exists(path):
|
|
24
|
-
cls._lib = ctypes.CDLL(path)
|
|
25
|
-
cls._setup_function_signatures()
|
|
26
|
-
return cls._lib
|
|
27
|
-
|
|
28
|
-
@classmethod
|
|
29
|
-
def _setup_function_signatures(cls):
|
|
30
|
-
lib = cls._lib
|
|
31
|
-
|
|
32
|
-
# init
|
|
33
|
-
lib.init.argtypes = [
|
|
34
|
-
ctypes.c_void_p, # sampler
|
|
35
|
-
ctypes.c_uint64, # length
|
|
36
|
-
ctypes.c_uint64, # batch_size
|
|
37
|
-
ctypes.c_uint8, # mode
|
|
38
|
-
ctypes.c_uint64 # seed
|
|
39
|
-
]
|
|
40
|
-
lib.init.restype = None
|
|
41
|
-
|
|
42
|
-
# size
|
|
43
|
-
lib.size.restype = ctypes.c_size_t
|
|
44
|
-
|
|
45
|
-
# next
|
|
46
|
-
lib.next.argtypes = [
|
|
47
|
-
ctypes.c_void_p, # sampler
|
|
48
|
-
ctypes.c_void_p # batch_indices
|
|
49
|
-
]
|
|
50
|
-
lib.next.restype = None
|
|
51
|
-
|
|
52
|
-
def __init__(self, length: int, batch_size: int, mode: int, seed: int = 42):
|
|
53
|
-
# import lib
|
|
54
|
-
self.lib = self._load_lib()
|
|
55
|
-
|
|
56
|
-
# sampler
|
|
57
|
-
self.sampler = ctypes.create_string_buffer(self.lib.size())
|
|
58
|
-
self.sampler_ptr = ctypes.cast(self.sampler, ctypes.c_void_p)
|
|
59
|
-
self.lib.init(self.sampler_ptr, length, batch_size, mode, seed)
|
|
60
|
-
|
|
61
|
-
# batch_indices
|
|
62
|
-
self.indices = np.zeros(batch_size, dtype=np.uint64)
|
|
63
|
-
self.indices_ptr = self.indices.ctypes.data
|
|
64
|
-
|
|
65
|
-
# step
|
|
66
|
-
def next(self):
|
|
67
|
-
self.lib.next(self.sampler_ptr, self.indices_ptr)
|
|
68
|
-
|
|
69
|
-
# iterator
|
|
70
|
-
def __iter__(self):
|
|
71
|
-
return self
|
|
72
|
-
def __next__(self):
|
|
73
|
-
self.next()
|
|
74
|
-
return self.indices
|
|
75
|
-
|
|
76
|
-
def run():
|
|
77
|
-
from itertools import islice
|
|
78
|
-
length = 10
|
|
79
|
-
batch_size = 4
|
|
80
|
-
n_steps = 5
|
|
81
|
-
|
|
82
|
-
print("=== Sampler SEQUENTIAL ===")
|
|
83
|
-
sampler = Sampler(length, batch_size, Sampler.Mode.SEQUENTIAL)
|
|
84
|
-
for indices in islice(sampler, n_steps):
|
|
85
|
-
print(indices)
|
|
86
|
-
|
|
87
|
-
print("=== Sampler IID ===")
|
|
88
|
-
sampler = Sampler(length, batch_size, Sampler.Mode.IID)
|
|
89
|
-
for indices in islice(sampler, n_steps):
|
|
90
|
-
print(indices)
|
|
91
|
-
|
|
92
|
-
# Benchmark, zig-sampler speeder 2.2x
|
|
93
|
-
def bench():
|
|
94
|
-
length = 1_000_000
|
|
95
|
-
batch_size = 8192
|
|
96
|
-
n_steps = 10_000
|
|
97
|
-
|
|
98
|
-
print("=== NumPy IID ===")
|
|
99
|
-
t0 = time.time()
|
|
100
|
-
batch = np.zeros(batch_size, dtype=np.uint64)
|
|
101
|
-
for _ in range(n_steps):
|
|
102
|
-
batch[:] = np.random.randint(0, length, size=batch_size, dtype=np.uint64)
|
|
103
|
-
print(f"{(time.time() - t0)*1000:.2f} ms")
|
|
104
|
-
|
|
105
|
-
print("=== Sampler IID ===")
|
|
106
|
-
t0 = time.time()
|
|
107
|
-
sampler = Sampler(length, batch_size, Sampler.Mode.IID)
|
|
108
|
-
for _ in range(n_steps):
|
|
109
|
-
sampler.next()
|
|
110
|
-
print(f"{(time.time() - t0)*1000:.2f} ms")
|
|
111
|
-
|
|
112
|
-
if __name__ == "__main__":
|
|
113
|
-
run()
|
|
114
|
-
bench()
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|