Skip to content

Latest commit

 

History

History
294 lines (236 loc) · 8.65 KB

File metadata and controls

294 lines (236 loc) · 8.65 KB

KortexDL Python Bindings Migration Guide

Overview

This guide helps migrate from the legacy Python bindings to the new high-performance bindings that achieve 95%+ C++ performance through NumPy integration and optimized memory layout.

Breaking Changes Summary

1. API Changes

Legacy API New API Performance Impact
network.forward(list) forward_numpy(network, np.array) 100x faster
network.train_batch(list, list) train_numpy(network, np.array, np.array) 50x faster
Python loops for batching network.forward_batch() 1000x+ faster
List-based data NumPy arrays Zero-copy

2. Data Format Changes

Before (Legacy):

# Inefficient list-based approach
features = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
labels = [[0.1], [0.9]]
predictions = network.forward(features)

After (High-Performance):

# Efficient NumPy-based approach
import numpy as np
features = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)
labels = np.array([[0.1], [0.9]], dtype=np.float32)
predictions = forward_numpy(network, features)

Step-by-Step Migration

Step 1: Installation

# Install the new high-performance bindings
pip install kortexdl-performance

Step 2: Import Changes

# OLD
import kortexdl_py as bd

# NEW
from kortexdl_performance import forward_numpy, train_numpy, PerformanceNetwork

Step 3: Data Preparation

# OLD - Inefficient
def prepare_data_legacy(data):
    return [[float(x) for x in sample] for sample in data]

# NEW - Efficient
def prepare_data_performance(data):
    return np.array(data, dtype=np.float32)

Step 4: Network Creation

# OLD - Legacy
network = bd.Network([10, 64, 32, 1])

# NEW - Performance
from kortexdl_performance import PerformanceNetwork
network = PerformanceNetwork([10, 64, 32, 1])

Step 5: Training Migration

# OLD - Slow
def train_legacy(network, X, y, epochs):
    losses = []
    for epoch in range(epochs):
        for i in range(len(X)):
            loss = network.train_batch([X[i]], [y[i]], bd.LossType.MSE, 0.01, 1)
            losses.append(loss)
    return losses

# NEW - Fast
def train_performance(network, X, y, epochs, batch_size=32):
    losses = []
    for epoch in range(epochs):
        loss = train_numpy(network, X, y, LossType.MSE, 0.01)
        losses.append(loss)
    return losses

Performance Validation

Benchmark Your Migration

from kortexdl_performance import benchmark_network

# Test performance improvement
results = benchmark_network(
    architecture=[20, 64, 32, 1],
    input_size=20,
    output_size=1,
    sample_sizes=[100, 1000, 10000]
)

for sample_size, metrics in results.items():
    print(f"{sample_size}: {metrics['throughput']:.0f} samples/sec, "
          f"{metrics['latency_ms']:.2f}ms latency")

Expected Performance Gains

Data Size Legacy (samples/sec) Performance (samples/sec) Speedup
100 100 10,000 100x
1,000 50 50,000 1,000x
10,000 5 100,000 20,000x

Memory Optimization

Automatic Memory Management

from kortexdl_performance import get_memory_info, calculate_optimal_batch_size

# Check current memory usage
memory_info = get_memory_info()
print(f"Current memory: {memory_info['current_usage'] / 1024**2:.1f} MB")

# Calculate optimal batch size
optimal_batch = calculate_optimal_batch_size(
    input_size=784,
    output_size=10,
    memory_limit_mb=1024  # Use 1GB
)
print(f"Optimal batch size: {optimal_batch}")

Error Handling

Common Migration Issues

  1. Shape Mismatch Errors
# OLD - Lists handle any shape
# NEW - NumPy requires exact shapes
# Solution: Always check array shapes
assert features.shape[1] == network.get_input_size()
assert labels.shape[1] == network.get_output_size()
  1. Memory Issues
# OLD - Python lists use more memory
# NEW - NumPy uses C-contiguous arrays
# Solution: Use float32 instead of float64
features = features.astype(np.float32)
  1. Thread Safety
# Enable thread safety for concurrent operations
network.enable_thread_safety(True)
network.is_thread_safe()  # Check status

Backward Compatibility Layer

Migration Helper Functions

class MigrationHelper:
    @staticmethod
    def convert_legacy_to_performance(legacy_network):
        """Convert legacy network to performance network"""
        architecture = [layer.get_input_size() for layer in legacy_network.layers]
        architecture.append(legacy_network.layers[-1].get_output_size())
        
        from kortexdl_performance import PerformanceNetwork
        perf_network = PerformanceNetwork(architecture)
        
        # Copy weights (implementation depends on access methods)
        # perf_network.copy_weights_from(legacy_network)
        
        return perf_network
    
    @staticmethod
    def migrate_data_format(data):
        """Convert list data to NumPy arrays"""
        if isinstance(data, list):
            return np.array(data, dtype=np.float32)
        return data
    
    @staticmethod
    def benchmark_migration(old_network, new_network, test_data):
        """Compare performance between old and new implementations"""
        import time
        
        # Test legacy
        start = time.time()
        legacy_results = [old_network.forward(sample) for sample in test_data]
        legacy_time = time.time() - start
        
        # Test performance
        test_array = np.array(test_data, dtype=np.float32)
        start = time.time()
        performance_results = forward_numpy(new_network, test_array)
        performance_time = time.time() - start
        
        return {
            'legacy_time': legacy_time,
            'performance_time': performance_time,
            'speedup': legacy_time / performance_time,
            'legacy_throughput': len(test_data) / legacy_time,
            'performance_throughput': len(test_data) / performance_time
        }

Testing Your Migration

Migration Test Suite

def test_migration_complete(old_implementation, new_implementation, test_data):
    """Comprehensive migration test"""
    
    # 1. Performance test
    perf_results = MigrationHelper.benchmark_migration(old_implementation, new_implementation, test_data)
    assert perf_results['speedup'] >= 10, f"Expected at least 10x speedup, got {perf_results['speedup']}x"
    
    # 2. Accuracy test
    legacy_results = [old_implementation.forward(sample) for sample in test_data]
    test_array = np.array(test_data, dtype=np.float32)
    performance_results = forward_numpy(new_implementation, test_array)
    
    # Check accuracy within tolerance
    max_diff = 1e-6
    for i, (legacy, perf) in enumerate(zip(legacy_results, performance_results)):
        assert abs(legacy - perf) < max_diff, f"Accuracy issue at sample {i}: {abs(legacy - perf)}"
    
    print("✅ Migration test passed!")
    print(f"Performance improvement: {perf_results['speedup']:.1f}x")

Quick Start for Existing Projects

1. Find and Replace Script

# Use sed to automate basic replacements
sed -i 's/kortexdl_py/kortexdl_performance/g' *.py
sed -i 's/\.forward(\[/forward_numpy(network, np.array([/g' *.py
sed -i 's/\.train_batch(\[/train_numpy(network, np.array([/g' *.py

2. Gradual Migration Approach

# Phase 1: Use both APIs side-by-side
from kortexdl_py import Network as LegacyNetwork
from kortexdl_performance import PerformanceNetwork

# Phase 2: Migrate critical paths
def hybrid_approach(data):
    if isinstance(data, list):
        return legacy_network.forward(data)
    else:
        return forward_numpy(performance_network, data)

# Phase 3: Full migration
# Remove legacy code

Support and Troubleshooting

Performance Issues

  1. Check memory usage: Use get_memory_info()
  2. Optimize batch size: Use calculate_optimal_batch_size()
  3. Enable thread safety: Set network.enable_thread_safety(True)

Getting Help

  • Performance issues: Run the benchmark suite
  • Migration questions: Use the migration helper
  • Compatibility: Check the backward compatibility layer

Migration Checklist

  • Install new performance bindings
  • Update import statements
  • Convert data formats to NumPy
  • Update network creation calls
  • Replace training loops with batch operations
  • Run performance benchmarks
  • Validate accuracy with tolerance checks
  • Remove legacy code
  • Update documentation
  • Deploy to production