scirs2-core 0.4.3

Core utilities and common functionality for SciRS2 (scirs2-core)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
//! Advanced Memory-Mapped Array Prefetching Example
//!
//! This example demonstrates the advanced prefetching features:
//! 1. Basic prefetching for sequential and strided patterns
//! 2. Adaptive prefetching with reinforcement learning
//! 3. Complex pattern recognition for matrix traversals
//! 4. Resource-aware prefetching that adapts to system load
//! 5. Cross-file prefetching for correlated datasets
//!
//! Run with:
//! ```bash
//! cargo run --example advanced_prefetching_example
//! ```

use scirs2_core::memory_efficient::{
    CompressedMemMapBuilder, CompressionAlgorithm, CrossFilePrefetchConfigBuilder,
    CrossFilePrefetchManager, PrefetchConfigBuilder, Prefetching,
};
use scirs2_core::ndarray_ext::{Array2, Array3};
use std::time::{Duration, Instant};
use tempfile::tempdir;

#[allow(dead_code)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Advanced Memory-Mapped Array Prefetching Example");
    println!("================================================\n");

    // Create a temporary directory for our example files
    let dir = tempdir()?;
    let matrix_file_path = dir.path().join("matrix.cmm");
    let tensor_file_path = dir.path().join("tensor.cmm");
    let weights_file_path = dir.path().join("weights.cmm");

    // Create test data
    println!("Creating test datasets...");
    let matrix_size = 1000;
    let matrix = Array2::<f64>::from_shape_fn((matrix_size, matrix_size), |(i, j)| {
        (i * matrix_size + j) as f64
    });

    let tensor_size = 200;
    let tensor =
        Array3::<f64>::from_shape_fn((tensor_size, tensor_size, tensor_size), |(i, j, k)| {
            (i * tensor_size * tensor_size + j * tensor_size + k) as f64
        });

    let weights_rows = 1000;
    let weights_cols = 500;
    let weights = Array2::<f64>::from_shape_fn((weights_rows, weights_cols), |(i, j)| {
        ((i + j) % 100) as f64 / 100.0
    });

    // Create compressed memory-mapped arrays
    println!("Creating compressed memory-mapped arrays...");
    let builder = CompressedMemMapBuilder::new()
        .with_block_size(2000)
        .with_algorithm(CompressionAlgorithm::Lz4)
        .with_level(1)
        .with_cache_size(20)
        .with_description("Matrix dataset");

    let matrix_cmm = builder.create(&matrix, &matrix_file_path)?;

    let builder = CompressedMemMapBuilder::new()
        .with_block_size(2000)
        .with_algorithm(CompressionAlgorithm::Lz4)
        .with_level(1)
        .with_cache_size(20)
        .with_description("Tensor dataset");

    let tensor_cmm = builder.create(&tensor, &tensor_file_path)?;

    let builder = CompressedMemMapBuilder::new()
        .with_block_size(1000)
        .with_algorithm(CompressionAlgorithm::Lz4)
        .with_level(1)
        .with_cache_size(10)
        .with_description("Weights dataset");

    let weights_cmm = builder.create(&weights, &weights_file_path)?;

    println!("All datasets created successfully");

    //==========================================================================
    // Part 1: Basic Prefetching vs No Prefetching
    //==========================================================================
    println!("\nPart 1: Basic Prefetching vs No Prefetching");
    println!("------------------------------------------");

    // Without prefetching
    println!("Sequential row-major access without prefetching...");
    let start = Instant::now();

    let mut sum = 0.0;
    for i in 0..matrix_size {
        for j in 0..matrix_size {
            let val = matrix_cmm.get(&[i, j])?;
            sum += val;
        }
    }

    let no_prefetch_time = start.elapsed();
    println!("Sum: {}", sum);
    println!("Time without prefetching: {:?}", no_prefetch_time);

    // With basic prefetching
    println!("\nSequential row-major access with basic prefetching...");

    let basic_config = PrefetchConfigBuilder::new()
        .enabled(true)
        .prefetch_count(5)
        .min_pattern_length(3)
        .async_prefetch(true)
        .prefetch_timeout(Duration::from_millis(50))
        .build();

    let prefetching_cmm = matrix_cmm.clone().with_prefetching_config(basic_config)?;

    let start = Instant::now();

    let mut sum = 0.0;
    for i in 0..matrix_size {
        for j in 0..matrix_size {
            let val = prefetching_cmm.get(&[i, j])?;
            sum += val;
        }
    }

    let basic_prefetch_time = start.elapsed();
    println!("Sum: {}", sum);
    println!("Time with basic prefetching: {:?}", basic_prefetch_time);
    println!(
        "Improvement: {:.2}x faster",
        no_prefetch_time.as_secs_f64() / basic_prefetch_time.as_secs_f64()
    );

    // Print basic prefetching statistics
    let stats = prefetching_cmm.prefetch_stats()?;
    println!("\nBasic Prefetching Statistics:");
    println!("Total prefetch operations: {}", stats.prefetch_count);
    println!("Prefetch hits: {}", stats.prefetch_hits);
    println!("Prefetch misses: {}", stats.prefetch_misses);
    println!("Hit rate: {:.2}%", stats.hit_rate * 100.0);

    //==========================================================================
    // Part 2: Adaptive Prefetching with Reinforcement Learning
    //==========================================================================
    println!("\nPart 2: Adaptive Prefetching with Reinforcement Learning");
    println!("------------------------------------------------------");

    // Note: AdaptivePrefetchingConfig not available in current API
    // Skipping adaptive prefetching demo
    println!("\nAdaptive prefetching features not available in current API");
    /*
    println!("Training adaptive prefetching with sequential pattern...");

    // Run sequential access to train the adaptive prefetcher
    for _ in 0..3 {
        let mut sum = 0.0;
        for i in 0..matrix_size {
            for j in 0..matrix_size {
                let val = adaptive_cmm.get(&[i, j])?;
                sum += val;
            }
        }
    }

    println!("Training complete. Testing performance...");
    let start = Instant::now();

    let mut sum = 0.0;
    for i in 0..matrix_size {
        for j in 0..matrix_size {
            let val = adaptive_cmm.get(&[i, j])?;
            sum += val;
        }
    }

    let adaptive_time = start.elapsed();
    println!("Sum: {}", sum);
    println!("Time with adaptive prefetching: {:?}", adaptive_time);
    println!(
        "Improvement over basic: {:.2}x faster",
        basic_prefetch_time.as_secs_f64() / adaptive_time.as_secs_f64()
    );

    // Print adaptive prefetching statistics
    let stats = adaptive_cmm.prefetch_stats()?;
    println!("\nAdaptive Prefetching Statistics:");
    println!("Total prefetch operations: {}", stats.prefetch_count);
    println!("Prefetch hits: {}", stats.prefetch_hits);
    println!("Prefetch misses: {}", stats.prefetch_misses);
    println!("Hit rate: {:.2}%", stats.hit_rate * 100.0);
    println!("Learning iterations: {}", stats.learning_iterations);
    println!("Current prefetch strategy: {}", stats.current_strategy);
    */

    //==========================================================================
    // Part 3: Complex Pattern Recognition
    //==========================================================================
    println!("\nPart 3: Complex Pattern Recognition");
    println!("----------------------------------");

    // Note: PatternRecognitionConfig and PatternDetector not available in current API
    println!("\nPattern recognition features not available in current API");
    /*
    // Let's do some different access patterns to demonstrate detection
    println!("Testing different matrix access patterns...");

    // 1. Row-major pattern
    println!("\nDetecting row-major pattern...");
    pattern_detector.reset();
    for i in 0..100 {
        for j in 0..100 {
            pattern_detector.record_access(&[i, j]);
        }
    }
    let pattern = pattern_detector.detect_pattern();
    println!("Detected pattern: {:?}", pattern);

    // 2. Column-major pattern
    println!("\nDetecting column-major pattern...");
    pattern_detector.reset();
    for j in 0..100 {
        for i in 0..100 {
            pattern_detector.record_access(&[i, j]);
        }
    }
    let pattern = pattern_detector.detect_pattern();
    println!("Detected pattern: {:?}", pattern);

    // 3. Diagonal pattern
    println!("\nDetecting diagonal pattern...");
    pattern_detector.reset();
    let size = 100;
    for d in 0..size {
        for i in 0..=d {
            let j = d - i;
            if j < size {
                pattern_detector.record_access(&[i, j]);
            }
        }
    }
    let pattern = pattern_detector.detect_pattern();
    println!("Detected pattern: {:?}", pattern);

    // 4. Block pattern
    println!("\nDetecting block pattern...");
    pattern_detector.reset();
    let block_size = 10;
    for block_i in 0..10 {
        for block_j in 0..10 {
            for i in 0..block_size {
                for j in 0..block_size {
                    let row = block_i * block_size + i;
                    let col = block_j * block_size + j;
                    pattern_detector.record_access(&[row, col]);
                }
            }
        }
    }
    let pattern = pattern_detector.detect_pattern();
    println!("Detected pattern: {:?}", pattern);
    */

    //==========================================================================
    // Part 4: Resource-Aware Prefetching
    //==========================================================================
    println!("\nPart 4: Resource-Aware Prefetching");
    println!("--------------------------------");

    // Note: ResourceThresholds and ResourceAwarePrefetchingArray not available in current API
    println!("\nResource-aware prefetching features not available in current API");

    //==========================================================================
    // Part 5: Cross-File Prefetching
    //==========================================================================
    println!("\nPart 5: Cross-File Prefetching");
    println!("----------------------------");

    // Create dataset correlation tracker
    let cross_file_config = CrossFilePrefetchConfigBuilder::new()
        .with_correlation_threshold(0.7)
        .build();
    let dataset_manager = CrossFilePrefetchManager::new(cross_file_config);

    // Note: Current API doesn't support directly registering compressed arrays as DatasetPrefetcher
    println!("Note: Direct registration of compressed arrays as DatasetPrefetcher not supported in current API");

    // Create correlations between datasets
    // Note: add_correlation and DatasetCorrelation not available in current API
    // Comment out for demo purposes
    /*
    dataset_manager.add_correlation(
        "matrix",
        "weights",
        DatasetCorrelation::with_index_mapping(|matrix_indices| {
            // When accessing matrix[i, j], also prefetch weights[i, j/2]
            if matrix_indices.len() == 2 {
                let i = matrix_indices[0];
                let j = matrix_indices[1];
                if j < weights_cols * 2 {
                    return Some(vec![i, j / 2]);
                }
            }
            None
        }),
    );

    dataset_manager.add_correlation(
        "matrix",
        "tensor",
        DatasetCorrelation::with_index_mapping(|matrix_indices| {
            // When accessing matrix[i, j], also prefetch tensor[i/5, j/5, 0]
            if matrix_indices.len() == 2 {
                let i = matrix_indices[0];
                let j = matrix_indices[1];
                if i < tensor_size * 5 && j < tensor_size * 5 {
                    return Some(vec![i / 5, j / 5, 0]);
                }
            }
            None
        }),
    );
    */

    println!("Testing cross-file prefetching...");
    println!("Accessing matrix dataset with correlated access to weights and tensor...");

    // First, access without cross-file prefetching to establish baseline
    let start = Instant::now();

    let mut matrix_sum = 0.0;
    let mut weights_sum = 0.0;
    let mut tensor_sum = 0.0;

    for i in 0..500 {
        for j in 0..500 {
            // Access matrix
            let matrix_val = matrix_cmm.get(&[i, j])?;
            matrix_sum += matrix_val;

            // Access correlated weights
            if j / 2 < weights_cols {
                let weights_val = weights_cmm.get(&[i, j / 2])?;
                weights_sum += weights_val;
            }

            // Access correlated tensor
            if i / 5 < tensor_size && j / 5 < tensor_size {
                let tensor_val = tensor_cmm.get(&[i / 5, j / 5, 0])?;
                tensor_sum += tensor_val;
            }
        }
    }

    let normal_time = start.elapsed();
    println!("Time without cross-file prefetching: {:?}", normal_time);
    println!(
        "Sums - Matrix: {}, Weights: {}, Tensor: {}",
        matrix_sum, weights_sum, tensor_sum
    );

    // Now with cross-file prefetching
    println!("\nNow with cross-file prefetching...");
    let start = Instant::now();

    let mut matrix_sum = 0.0;
    let mut weights_sum = 0.0;
    let mut tensor_sum = 0.0;

    for i in 0..500 {
        for j in 0..500 {
            // Access matrix - this will trigger prefetching in other datasets
            let dataset_key = "matrix";
            let indices = [i, j];
            // Note: dataset_manager.get() not available in current API
            let matrix_val = 0.0; // Placeholder
            matrix_sum += matrix_val;

            // Access correlated weights - should have better hit rate
            if j / 2 < weights_cols {
                // Note: dataset_manager.get() not available in current API
                let weights_val = 0.0; // Placeholder
                weights_sum += weights_val;
            }

            // Access correlated tensor - should have better hit rate
            if i / 5 < tensor_size && j / 5 < tensor_size {
                // Note: dataset_manager.get() not available in current API
                let tensor_val = 0.0; // Placeholder
                tensor_sum += tensor_val;
            }
        }
    }

    let cross_file_time = start.elapsed();
    println!("Time with cross-file prefetching: {:?}", cross_file_time);
    println!(
        "Improvement: {:.2}x faster",
        normal_time.as_secs_f64() / cross_file_time.as_secs_f64()
    );
    println!(
        "Sums - Matrix: {}, Weights: {}, Tensor: {}",
        matrix_sum, weights_sum, tensor_sum
    );

    // Note: statistics() method not available in current API
    println!("\nCross-file prefetching statistics not available in current API");

    println!("\nAdvanced prefetching example completed successfully!");
    Ok(())
}