0
# Input/Output Operations
1
2
File I/O operations supporting NumPy's binary formats (NPZ) and text formats with GPU-optimized loading and saving capabilities. CuPy provides comprehensive file operations for data persistence and exchange between CPU and GPU memory spaces.
3
4
## Capabilities
5
6
### Binary Format Operations
7
8
High-performance binary file operations for efficient data storage and loading.
9
10
```python { .api }
11
def save(file, arr, allow_pickle=True, fix_imports=True):
12
"""Save array to binary file in NumPy format.
13
14
Args:
15
file: File path or file object
16
arr: Array to save
17
allow_pickle: Allow pickling of Python objects
18
fix_imports: Fix Python 2/3 compatibility
19
20
Note:
21
Saves in uncompressed .npy format
22
"""
23
24
def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII'):
25
"""Load array from binary file.
26
27
Args:
28
file: File path or file object
29
mmap_mode: Memory mapping mode (None, 'r', 'r+', 'w+', 'c')
30
allow_pickle: Allow loading pickled objects
31
fix_imports: Fix Python 2/3 compatibility
32
encoding: String encoding for Python 2/3 compatibility
33
34
Returns:
35
cupy.ndarray: Loaded array on GPU
36
"""
37
38
def savez(file, *args, **kwds):
39
"""Save multiple arrays to compressed archive.
40
41
Args:
42
file: Output file path
43
*args: Arrays to save (saved as arr_0, arr_1, ...)
44
**kwds: Named arrays to save
45
46
Note:
47
Creates uncompressed .npz archive
48
"""
49
50
def savez_compressed(file, *args, **kwds):
51
"""Save multiple arrays to compressed archive.
52
53
Args:
54
file: Output file path
55
*args: Arrays to save (saved as arr_0, arr_1, ...)
56
**kwds: Named arrays to save
57
58
Note:
59
Creates compressed .npz archive with better compression
60
"""
61
62
def loadz(file):
63
"""Load arrays from .npz archive.
64
65
Args:
66
file: Path to .npz file
67
68
Returns:
69
NpzFile: Dictionary-like object for array access
70
"""
71
```
72
73
### Text Format Operations
74
75
Text-based file operations for human-readable data exchange and compatibility.
76
77
```python { .api }
78
def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n',
79
header='', footer='', comments='# ', encoding=None):
80
"""Save array to text file.
81
82
Args:
83
fname: Output filename
84
X: Array to save (1D or 2D)
85
fmt: Format string or sequence of format strings
86
delimiter: String/character separating columns
87
newline: String/character separating lines
88
header: Text to write at beginning of file
89
footer: Text to write at end of file
90
comments: String to prepend to header/footer
91
encoding: Text encoding
92
93
Note:
94
Data is transferred to CPU before saving
95
"""
96
97
def loadtxt(fname, dtype=float, comments='#', delimiter=None,
98
converters=None, skiprows=0, usecols=None, unpack=False,
99
ndmin=0, encoding='bytes', max_rows=None):
100
"""Load data from text file.
101
102
Args:
103
fname: Input filename
104
dtype: Data type of resulting array
105
comments: Character(s) indicating start of comment
106
delimiter: String used to separate values
107
converters: Dictionary of converter functions
108
skiprows: Number of rows to skip at beginning
109
usecols: Columns to read (None for all)
110
unpack: Unpack columns into separate arrays
111
ndmin: Minimum dimensions of returned array
112
encoding: Text encoding
113
max_rows: Maximum number of rows to read
114
115
Returns:
116
cupy.ndarray: Loaded data on GPU
117
"""
118
119
def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
120
skip_header=0, skip_footer=0, converters=None,
121
missing_values=None, filling_values=None, usecols=None,
122
names=None, excludelist=None, deletechars=None,
123
defaultfmt='f%i', autostrip=False, replace_space='_',
124
case_sensitive=True, unpack=None, invalid_raise=True,
125
max_rows=None, encoding='bytes'):
126
"""Enhanced text loading with missing value support.
127
128
Args:
129
fname: Input filename
130
dtype: Data type
131
comments: Comment character(s)
132
delimiter: Value separator
133
skip_header: Lines to skip at beginning
134
skip_footer: Lines to skip at end
135
converters: Converter functions
136
missing_values: Strings indicating missing data
137
filling_values: Values for missing data
138
usecols: Columns to use
139
names: Field names for structured arrays
140
excludelist: Names of fields to exclude
141
deletechars: Characters to remove from field names
142
defaultfmt: Default format for field names
143
autostrip: Strip whitespace from values
144
replace_space: Character to replace spaces in names
145
case_sensitive: Case sensitivity for field names
146
unpack: Unpack arrays
147
invalid_raise: Raise exception on invalid values
148
max_rows: Maximum rows to read
149
encoding: Text encoding
150
151
Returns:
152
cupy.ndarray: Loaded data with missing value handling
153
"""
154
```
155
156
### Array String Representation
157
158
Functions for converting arrays to string representations and formatting.
159
160
```python { .api }
161
def array_str(a, max_line_width=None, precision=None, suppress_small=None):
162
"""Return string representation of array data.
163
164
Args:
165
a: Input array
166
max_line_width: Maximum characters per line
167
precision: Floating point precision
168
suppress_small: Suppress small values in scientific notation
169
170
Returns:
171
str: String representation of array data
172
"""
173
174
def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
175
"""Return string representation of array.
176
177
Args:
178
arr: Input array
179
max_line_width: Maximum characters per line
180
precision: Floating point precision
181
suppress_small: Suppress small values
182
183
Returns:
184
str: String representation including array constructor
185
"""
186
187
def array2string(a, max_line_width=None, precision=None, suppress_small=None,
188
separator=' ', prefix="", style=str, formatter=None,
189
threshold=None, edgeitems=None, sign=None,
190
floatmode=None, suffix="", **kwds):
191
"""Return string representation with comprehensive formatting.
192
193
Args:
194
a: Input array
195
max_line_width: Maximum line width
196
precision: Number precision
197
suppress_small: Suppress small values
198
separator: Element separator
199
prefix: String prefix
200
style: Formatting style function
201
formatter: Custom formatting functions
202
threshold: Total items threshold for summarization
203
edgeitems: Items at beginning/end in summary
204
sign: Sign handling (' ', '+', '-')
205
floatmode: Float formatting mode
206
suffix: String suffix
207
**kwds: Additional formatting parameters
208
209
Returns:
210
str: Formatted string representation
211
"""
212
213
def base_repr(number, base=2, padding=0):
214
"""Return string representation in given base.
215
216
Args:
217
number: Input number
218
base: Number base (2-36)
219
padding: Minimum width with zero padding
220
221
Returns:
222
str: String representation in specified base
223
"""
224
```
225
226
### Memory Mapping and Direct Access
227
228
Advanced file operations for memory-mapped arrays and direct disk access.
229
230
```python { .api }
231
def memmap(filename, dtype='uint8', mode='r+', offset=0, shape=None, order='C'):
232
"""Create memory-mapped array.
233
234
Args:
235
filename: Path to file
236
dtype: Data type
237
mode: File access mode ('r', 'r+', 'w+', 'c')
238
offset: Byte offset in file
239
shape: Array shape (required for modes other than 'r')
240
order: Memory layout ('C' or 'F')
241
242
Returns:
243
numpy.memmap: Memory-mapped array (CPU-based)
244
245
Note:
246
Returns NumPy memmap object. Use cp.asarray() to copy to GPU.
247
"""
248
249
def fromfile(file, dtype=float, count=-1, sep='', offset=0):
250
"""Create array from binary or text file data.
251
252
Args:
253
file: Open file object or filename
254
dtype: Data type of array elements
255
count: Number of items to read (-1 for all)
256
sep: Separator for text files (empty for binary)
257
offset: Byte offset for binary files
258
259
Returns:
260
cupy.ndarray: Array created from file data
261
"""
262
263
def tofile(arr, fid, sep="", format="%s"):
264
"""Write array to file as text or binary.
265
266
Args:
267
arr: Input array
268
fid: Open file object or filename
269
sep: Separator for text output (empty for binary)
270
format: Format string for text output
271
272
Note:
273
Data is transferred to CPU before writing
274
"""
275
276
def fromstring(string, dtype=float, count=-1, sep=''):
277
"""Create array from string data.
278
279
Args:
280
string: Input string
281
dtype: Data type
282
count: Number of items (-1 for all)
283
sep: Separator character
284
285
Returns:
286
cupy.ndarray: Array from string data
287
"""
288
289
def frombuffer(buffer, dtype=float, count=-1, offset=0):
290
"""Create array from buffer object.
291
292
Args:
293
buffer: Buffer object (bytes-like)
294
dtype: Data type
295
count: Number of items (-1 for all)
296
offset: Byte offset in buffer
297
298
Returns:
299
cupy.ndarray: Array from buffer data
300
"""
301
```
302
303
### Configuration and Formatting Control
304
305
Functions for controlling array display and I/O behavior.
306
307
```python { .api }
308
def set_printoptions(precision=None, threshold=None, edgeitems=None,
309
linewidth=None, suppress=None, nanstr=None,
310
infstr=None, formatter=None, sign=None,
311
floatmode=None, **kwds):
312
"""Set printing options for arrays.
313
314
Args:
315
precision: Number of digits of precision
316
threshold: Total array elements triggering summarization
317
edgeitems: Number of edge items in summary mode
318
linewidth: Characters per line for wrapping
319
suppress: Suppress small floating point values
320
nanstr: String representation of NaN values
321
infstr: String representation of infinity values
322
formatter: Custom formatting functions
323
sign: Control sign display
324
floatmode: Floating point formatting mode
325
**kwds: Additional options
326
"""
327
328
def get_printoptions():
329
"""Return current print options.
330
331
Returns:
332
dict: Current printing configuration
333
"""
334
335
def printoptions(*args, **kwargs):
336
"""Context manager for temporary print options.
337
338
Args:
339
*args, **kwargs: Print option arguments
340
341
Returns:
342
Context manager for temporary option changes
343
"""
344
345
def set_string_function(f, repr=True):
346
"""Set function for array string representation.
347
348
Args:
349
f: Function to use for string conversion
350
repr: Whether function is for repr (True) or str (False)
351
"""
352
```
353
354
### Data Exchange and Interoperability
355
356
Functions for converting between different data formats and libraries.
357
358
```python { .api }
359
def asarray(a, dtype=None, order=None):
360
"""Convert input to CuPy array.
361
362
Args:
363
a: Input data (any array-like)
364
dtype: Data type
365
order: Memory layout
366
367
Returns:
368
cupy.ndarray: Array on GPU
369
"""
370
371
def asnumpy(a, stream=None, order='C', out=None):
372
"""Convert CuPy array to NumPy array.
373
374
Args:
375
a: Input CuPy array
376
stream: CUDA stream for asynchronous transfer
377
order: Memory layout ('C', 'F', 'A', 'K')
378
out: Output NumPy array
379
380
Returns:
381
numpy.ndarray: Array on CPU
382
"""
383
384
def from_dlpack(x):
385
"""Create CuPy array from DLPack tensor.
386
387
Args:
388
x: Object with __dlpack__ method
389
390
Returns:
391
cupy.ndarray: Array sharing memory with DLPack tensor
392
"""
393
394
def fromDlpack(dltensor):
395
"""Create array from DLPack tensor capsule.
396
397
Args:
398
dltensor: DLPack tensor capsule
399
400
Returns:
401
cupy.ndarray: Array from DLPack tensor
402
"""
403
```
404
405
### Compression and Archive Operations
406
407
Advanced operations for compressed data and multi-file archives.
408
409
```python { .api }
410
class NpzFile:
411
"""Object for reading .npz archive files.
412
413
Provides dictionary-like access to arrays stored in .npz files.
414
415
Attributes:
416
files: List of file names in archive
417
418
Methods:
419
close(): Close the archive file
420
__getitem__(key): Get array by name
421
__contains__(key): Check if array exists
422
__iter__(): Iterate over array names
423
"""
424
425
def __init__(self, fid, own_fid=False, allow_pickle=False,
426
pickle_kwargs=None):
427
pass
428
429
def __enter__(self):
430
return self
431
432
def __exit__(self, exc_type, exc_value, traceback):
433
self.close()
434
435
def close(self):
436
"""Close the archive file."""
437
pass
438
439
def __getitem__(self, key):
440
"""Load array from archive."""
441
pass
442
443
def save_compressed(file, **arrays):
444
"""Save arrays to compressed archive with optimal compression.
445
446
Args:
447
file: Output file path
448
**arrays: Named arrays to save
449
450
Note:
451
Uses advanced compression for minimal file size
452
"""
453
454
def load_archive(file, lazy=False):
455
"""Load archive with optional lazy loading.
456
457
Args:
458
file: Archive file path
459
lazy: Load arrays only when accessed
460
461
Returns:
462
dict or NpzFile: Archive contents
463
"""
464
```
465
466
## Usage Examples
467
468
### Basic File Operations
469
470
```python
471
import cupy as cp
472
import numpy as np
473
474
# Create sample data
475
data = cp.random.randn(1000, 100).astype(cp.float32)
476
labels = cp.random.randint(0, 10, 1000)
477
metadata = {'version': '1.0', 'description': 'Sample dataset'}
478
479
print(f"Data shape: {data.shape}, dtype: {data.dtype}")
480
print(f"Labels shape: {labels.shape}, dtype: {labels.dtype}")
481
482
# Save single array to binary format
483
cp.save('data.npy', data)
484
print("Saved data to 'data.npy'")
485
486
# Load single array
487
loaded_data = cp.load('data.npy')
488
print(f"Loaded data shape: {loaded_data.shape}")
489
print(f"Arrays equal: {cp.array_equal(data, loaded_data)}")
490
491
# Save multiple arrays to archive
492
cp.savez('dataset.npz',
493
features=data,
494
targets=labels,
495
train_indices=cp.arange(800),
496
test_indices=cp.arange(800, 1000))
497
print("Saved multiple arrays to 'dataset.npz'")
498
499
# Load from archive
500
with cp.load('dataset.npz') as archive:
501
print(f"Archive files: {archive.files}")
502
features = archive['features']
503
targets = archive['targets']
504
train_idx = archive['train_indices']
505
test_idx = archive['test_indices']
506
507
print(f"Loaded features shape: {features.shape}")
508
print(f"Loaded targets shape: {targets.shape}")
509
print(f"Train samples: {len(train_idx)}")
510
print(f"Test samples: {len(test_idx)}")
511
512
# Compressed saving for better storage efficiency
513
cp.savez_compressed('dataset_compressed.npz',
514
features=data,
515
targets=labels,
516
metadata=str(metadata))
517
print("Saved compressed archive to 'dataset_compressed.npz'")
518
```
519
520
### Text File Operations
521
522
```python
523
import cupy as cp
524
import os
525
526
# Create sample numeric data
527
measurements = cp.array([
528
[1.23, 4.56, 7.89],
529
[2.34, 5.67, 8.90],
530
[3.45, 6.78, 9.01],
531
[4.56, 7.89, 0.12]
532
])
533
534
# Save to text file with custom formatting
535
header_text = "Time Temperature Humidity"
536
cp.savetxt('measurements.txt', measurements,
537
fmt='%.2f',
538
delimiter='\t',
539
header=header_text,
540
comments='# ')
541
542
print("Saved measurements to 'measurements.txt'")
543
544
# Read the file content
545
with open('measurements.txt', 'r') as f:
546
content = f.read()
547
print("File contents:")
548
print(content)
549
550
# Load from text file
551
loaded_measurements = cp.loadtxt('measurements.txt')
552
print(f"Loaded measurements shape: {loaded_measurements.shape}")
553
print(f"Arrays equal: {cp.allclose(measurements, loaded_measurements)}")
554
555
# Load specific columns
556
time_temp = cp.loadtxt('measurements.txt', usecols=(0, 1))
557
print(f"Time and temperature shape: {time_temp.shape}")
558
559
# Advanced text loading with missing values
560
# Create data with missing values
561
mixed_data_text = """# Weather data
562
1.0 2.5 normal
563
2.0 nan windy
564
3.0 1.8 normal
565
nan 3.2 storm
566
5.0 2.1 normal"""
567
568
with open('weather.txt', 'w') as f:
569
f.write(mixed_data_text)
570
571
# Load with missing value handling
572
try:
573
weather_data = cp.genfromtxt('weather.txt',
574
missing_values={'nan': cp.nan},
575
filling_values={'nan': -999},
576
usecols=(0, 1), # Only numeric columns
577
dtype=float)
578
579
print(f"Weather data with missing values:")
580
print(weather_data)
581
print(f"NaN count: {cp.sum(cp.isnan(weather_data))}")
582
except Exception as e:
583
print(f"Error loading weather data: {e}")
584
```
585
586
### Large File Handling and Performance
587
588
```python
589
import cupy as cp
590
import time
591
import os
592
593
# Create large dataset for performance testing
594
n_samples = 100_000
595
n_features = 200
596
large_data = cp.random.randn(n_samples, n_features).astype(cp.float32)
597
598
print(f"Large dataset: {large_data.shape}, "
599
f"size: {large_data.nbytes / 1024**2:.1f} MB")
600
601
# Time different saving methods
602
save_methods = [
603
('Uncompressed NPY', lambda: cp.save('large_data.npy', large_data)),
604
('Uncompressed NPZ', lambda: cp.savez('large_data.npz', data=large_data)),
605
('Compressed NPZ', lambda: cp.savez_compressed('large_compressed.npz', data=large_data)),
606
]
607
608
file_sizes = {}
609
for name, save_func in save_methods:
610
start_time = time.perf_counter()
611
save_func()
612
cp.cuda.Stream.null.synchronize() # Wait for GPU operations
613
end_time = time.perf_counter()
614
615
# Get file size
616
if 'NPY' in name:
617
filename = 'large_data.npy'
618
elif 'Compressed' in name:
619
filename = 'large_compressed.npz'
620
else:
621
filename = 'large_data.npz'
622
623
file_size = os.path.getsize(filename) / 1024**2 # MB
624
file_sizes[name] = file_size
625
626
print(f"{name}: {(end_time - start_time)*1000:.1f} ms, "
627
f"file size: {file_size:.1f} MB")
628
629
# Time loading methods
630
load_methods = [
631
('Load NPY', lambda: cp.load('large_data.npy')),
632
('Load NPZ', lambda: cp.load('large_data.npz')['data']),
633
('Load Compressed', lambda: cp.load('large_compressed.npz')['data']),
634
]
635
636
for name, load_func in load_methods:
637
start_time = time.perf_counter()
638
loaded = load_func()
639
cp.cuda.Stream.null.synchronize()
640
end_time = time.perf_counter()
641
642
# Verify data integrity
643
is_equal = cp.array_equal(large_data, loaded)
644
645
print(f"{name}: {(end_time - start_time)*1000:.1f} ms, "
646
f"data integrity: {is_equal}")
647
648
# Demonstrate chunked processing for very large files
649
chunk_size = 10_000
650
print(f"\nProcessing data in chunks of {chunk_size:,} samples:")
651
652
# Save data in chunks
653
for i in range(0, n_samples, chunk_size):
654
chunk_end = min(i + chunk_size, n_samples)
655
chunk_data = large_data[i:chunk_end]
656
657
# Save each chunk
658
chunk_filename = f'chunk_{i//chunk_size:03d}.npy'
659
cp.save(chunk_filename, chunk_data)
660
661
if i < 3 * chunk_size: # Show first few chunks
662
print(f"Saved chunk {i//chunk_size + 1}: "
663
f"samples {i:,} to {chunk_end:,}")
664
665
print("Chunked saving completed")
666
```
667
668
### Memory-Mapped Files and Direct Access
669
670
```python
671
import cupy as cp
672
import numpy as np
673
import os
674
675
# Create large file for memory mapping demonstration
676
n_elements = 1_000_000
677
dtype = np.float32
678
679
# Create memory-mapped file
680
filename = 'large_memmap.dat'
681
mmap_array = np.memmap(filename, dtype=dtype, mode='w+', shape=(n_elements,))
682
683
# Fill with data (on CPU)
684
mmap_array[:] = np.random.randn(n_elements).astype(dtype)
685
mmap_array.flush() # Ensure data is written to disk
686
687
print(f"Created memory-mapped file: {filename}")
688
print(f"File size: {os.path.getsize(filename) / 1024**2:.1f} MB")
689
690
# Read portions of the file to GPU
691
chunk_size = 100_000
692
693
# Method 1: Load specific ranges
694
start_idx = 200_000
695
end_idx = start_idx + chunk_size
696
gpu_chunk = cp.asarray(mmap_array[start_idx:end_idx])
697
698
print(f"Loaded chunk [{start_idx:,}:{end_idx:,}] to GPU")
699
print(f"Chunk statistics: mean={cp.mean(gpu_chunk):.3f}, "
700
f"std={cp.std(gpu_chunk):.3f}")
701
702
# Method 2: Process file in streaming fashion
703
def process_large_file(filename, chunk_size=50_000):
704
"""Process large memory-mapped file in chunks."""
705
# Open as memory-mapped array
706
mmap_data = np.memmap(filename, dtype=dtype, mode='r')
707
n_total = len(mmap_data)
708
709
results = []
710
for i in range(0, n_total, chunk_size):
711
chunk_end = min(i + chunk_size, n_total)
712
713
# Load chunk to GPU
714
gpu_chunk = cp.asarray(mmap_data[i:chunk_end])
715
716
# Process chunk (example: compute statistics)
717
chunk_stats = {
718
'start': i,
719
'end': chunk_end,
720
'mean': float(cp.mean(gpu_chunk)),
721
'std': float(cp.std(gpu_chunk)),
722
'min': float(cp.min(gpu_chunk)),
723
'max': float(cp.max(gpu_chunk))
724
}
725
results.append(chunk_stats)
726
727
if i < 5 * chunk_size: # Show first few chunks
728
print(f"Chunk {i//chunk_size + 1}: "
729
f"mean={chunk_stats['mean']:.3f}, "
730
f"std={chunk_stats['std']:.3f}")
731
732
return results
733
734
# Process the large file
735
chunk_results = process_large_file(filename)
736
print(f"Processed {len(chunk_results)} chunks")
737
738
# Aggregate results
739
overall_mean = np.mean([r['mean'] for r in chunk_results])
740
print(f"Overall mean (approximate): {overall_mean:.3f}")
741
742
# Direct file operations
743
# Save array directly from GPU to file
744
gpu_data = cp.random.randn(50_000).astype(cp.float32)
745
with open('direct_output.bin', 'wb') as f:
746
# Convert to CPU and save
747
cpu_data = cp.asnumpy(gpu_data)
748
f.write(cpu_data.tobytes())
749
750
print(f"Saved GPU data directly to binary file")
751
752
# Read binary data back
753
with open('direct_output.bin', 'rb') as f:
754
raw_bytes = f.read()
755
recovered_data = cp.frombuffer(raw_bytes, dtype=cp.float32)
756
757
print(f"Recovered data shape: {recovered_data.shape}")
758
print(f"Data integrity: {cp.array_equal(gpu_data, recovered_data)}")
759
```
760
761
### Array Formatting and Display
762
763
```python
764
import cupy as cp
765
766
# Create sample arrays for formatting examples
767
small_array = cp.array([1.23456789, -2.3456789, 0.0001234])
768
large_array = cp.random.randn(100, 50)
769
integer_array = cp.arange(1000).reshape(10, 100)
770
771
# Basic string representations
772
print("Array string representations:")
773
print(f"Small array str: {cp.array_str(small_array)}")
774
print(f"Small array repr: {cp.array_repr(small_array)}")
775
776
# Custom formatting options
777
formatted = cp.array2string(small_array,
778
precision=3,
779
suppress_small=True,
780
separator=', ')
781
print(f"Custom formatted: {formatted}")
782
783
# Set global print options
784
original_options = cp.get_printoptions()
785
print(f"Original print options: {original_options}")
786
787
# Temporarily change print options
788
with cp.printoptions(precision=2, suppress=True, threshold=20):
789
print("With custom print options:")
790
print(f"Small array: {small_array}")
791
print(f"Large array (summarized):\n{large_array}")
792
793
# Demonstrate different formatting styles
794
print("\nDifferent formatting styles:")
795
796
# Scientific notation
797
scientific = cp.array2string(small_array,
798
formatter={'float_kind': lambda x: f'{x:.2e}'})
799
print(f"Scientific: {scientific}")
800
801
# Fixed point
802
fixed_point = cp.array2string(small_array,
803
formatter={'float_kind': lambda x: f'{x:.4f}'})
804
print(f"Fixed point: {fixed_point}")
805
806
# Custom separators and brackets
807
custom_format = cp.array2string(small_array,
808
separator=' | ',
809
prefix='[',
810
suffix=']',
811
formatter={'float_kind': lambda x: f'{x:+.2f}'})
812
print(f"Custom format: {custom_format}")
813
814
# Integer formatting in different bases
815
binary_repr = cp.base_repr(42, base=2, padding=8)
816
hex_repr = cp.base_repr(42, base=16)
817
octal_repr = cp.base_repr(42, base=8)
818
819
print(f"\nNumber 42 in different bases:")
820
print(f"Binary (base 2): {binary_repr}")
821
print(f"Hexadecimal (base 16): {hex_repr}")
822
print(f"Octal (base 8): {octal_repr}")
823
824
# Array info for debugging
825
def array_info(arr, name="Array"):
826
"""Print comprehensive array information."""
827
print(f"\n{name} Information:")
828
print(f" Shape: {arr.shape}")
829
print(f" Dtype: {arr.dtype}")
830
print(f" Size: {arr.size:,} elements")
831
print(f" Memory: {arr.nbytes / 1024**2:.2f} MB")
832
print(f" Min/Max: {cp.min(arr):.3f} / {cp.max(arr):.3f}")
833
print(f" Mean/Std: {cp.mean(arr):.3f} / {cp.std(arr):.3f}")
834
835
# Show sample of data
836
if arr.size <= 20:
837
print(f" Data: {arr}")
838
else:
839
flat = arr.flatten()
840
sample = cp.concatenate([flat[:5], flat[-5:]])
841
print(f" Sample: [{sample[0]:.3f}, {sample[1]:.3f}, ..., "
842
f"{sample[-2]:.3f}, {sample[-1]:.3f}]")
843
844
# Demonstrate array info function
845
array_info(small_array, "Small Array")
846
array_info(large_array, "Large Array")
847
array_info(integer_array, "Integer Array")
848
```
849
850
### Data Conversion and Interoperability
851
852
```python
853
import cupy as cp
854
import numpy as np
855
856
# Demonstrate conversion between CuPy and NumPy
857
print("GPU ↔ CPU Data Transfer:")
858
859
# Create data on GPU
860
gpu_data = cp.random.randn(1000, 500).astype(cp.float32)
861
print(f"GPU data: shape={gpu_data.shape}, device={gpu_data.device}")
862
863
# Transfer to CPU
864
cpu_data = cp.asnumpy(gpu_data)
865
print(f"CPU data: shape={cpu_data.shape}, type={type(cpu_data)}")
866
867
# Transfer back to GPU
868
gpu_data2 = cp.asarray(cpu_data)
869
print(f"Back to GPU: shape={gpu_data2.shape}, device={gpu_data2.device}")
870
print(f"Data integrity: {cp.array_equal(gpu_data, gpu_data2)}")
871
872
# Demonstrate asynchronous transfer with streams
873
stream1 = cp.cuda.Stream()
874
stream2 = cp.cuda.Stream()
875
876
print("\nAsynchronous transfers:")
877
large_gpu_data = cp.random.randn(5000, 1000)
878
879
with stream1:
880
# Asynchronous transfer to CPU
881
cpu_result1 = cp.asnumpy(large_gpu_data[:2500], stream=stream1)
882
883
with stream2:
884
# Asynchronous transfer to CPU
885
cpu_result2 = cp.asnumpy(large_gpu_data[2500:], stream=stream2)
886
887
# Wait for transfers to complete
888
stream1.synchronize()
889
stream2.synchronize()
890
891
print(f"Async transfer 1 completed: {cpu_result1.shape}")
892
print(f"Async transfer 2 completed: {cpu_result2.shape}")
893
894
# Combine results
895
combined_cpu = np.concatenate([cpu_result1, cpu_result2])
896
print(f"Combined result: {combined_cpu.shape}")
897
print(f"Transfer integrity: {np.array_equal(cp.asnumpy(large_gpu_data), combined_cpu)}")
898
899
# Demonstrate zero-copy operations where possible
900
print("\nMemory sharing and zero-copy operations:")
901
902
# Create GPU array
903
original_gpu = cp.arange(1000)
904
print(f"Original GPU array: {original_gpu.shape}")
905
906
# Create view (shares memory)
907
gpu_view = original_gpu[::2] # Every other element
908
print(f"GPU view: {gpu_view.shape}, shares memory: {cp.shares_memory(original_gpu, gpu_view)}")
909
910
# Modify view
911
gpu_view *= 10
912
913
# Check if original was modified
914
print(f"Original modified through view: {cp.sum(original_gpu != cp.arange(1000)) > 0}")
915
print(f"First few elements of original: {original_gpu[:10]}")
916
917
# DLPack interoperability (if available)
918
try:
919
# Convert to DLPack tensor
920
dlpack_tensor = gpu_data.__dlpack__()
921
922
# Create new array from DLPack tensor
923
from_dlpack = cp.from_dlpack(dlpack_tensor)
924
925
print(f"\nDLPack interoperability:")
926
print(f"Original shape: {gpu_data.shape}")
927
print(f"From DLPack shape: {from_dlpack.shape}")
928
print(f"Memory shared: {cp.shares_memory(gpu_data, from_dlpack)}")
929
930
except Exception as e:
931
print(f"DLPack not available: {e}")
932
933
# Clean up files created in examples
934
import os
935
files_to_clean = [
936
'data.npy', 'dataset.npz', 'dataset_compressed.npz',
937
'measurements.txt', 'weather.txt', 'large_data.npy',
938
'large_data.npz', 'large_compressed.npz', 'large_memmap.dat',
939
'direct_output.bin'
940
]
941
942
for filename in files_to_clean:
943
if os.path.exists(filename):
944
os.remove(filename)
945
946
# Clean up chunk files
947
for i in range(100): # Arbitrary upper limit
948
chunk_file = f'chunk_{i:03d}.npy'
949
if os.path.exists(chunk_file):
950
os.remove(chunk_file)
951
952
print("\nCleaned up temporary files")
953
```