feat: implement v0.2.0 release features - agent-first evolution
✅ v0.2 Release Preparation: - Update version to 0.2.0 in pyproject.toml - Create release build script for CLI binaries - Generate comprehensive release notes ✅ OpenClaw DAO Governance: - Implement complete on-chain voting system - Create DAO smart contract with Governor framework - Add comprehensive CLI commands for DAO operations - Support for multiple proposal types and voting mechanisms ✅ GPU Acceleration CI: - Complete GPU benchmark CI workflow - Comprehensive performance testing suite - Automated benchmark reports and comparison - GPU optimization monitoring and alerts ✅ Agent SDK Documentation: - Complete SDK documentation with examples - Computing agent and oracle agent examples - Comprehensive API reference and guides - Security best practices and deployment guides ✅ Production Security Audit: - Comprehensive security audit framework - Detailed security assessment (72.5/100 score) - Critical issues identification and remediation - Security roadmap and improvement plan ✅ Mobile Wallet & One-Click Miner: - Complete mobile wallet architecture design - One-click miner implementation plan - Cross-platform integration strategy - Security and user experience considerations ✅ Documentation Updates: - Add roadmap badge to README - Update project status and achievements - Comprehensive feature documentation - Production readiness indicators 🚀 Ready for v0.2.0 release with agent-first architecture
This commit is contained in:
320
dev/gpu/generate_benchmark_report.py
Normal file
320
dev/gpu/generate_benchmark_report.py
Normal file
@@ -0,0 +1,320 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
GPU Benchmark Report Generator
|
||||
Generates HTML reports from benchmark results
|
||||
"""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any
|
||||
import matplotlib.pyplot as plt
|
||||
import seaborn as sns
|
||||
|
||||
def load_benchmark_results(filename: str) -> Dict:
|
||||
"""Load benchmark results from JSON file"""
|
||||
with open(filename, 'r') as f:
|
||||
return json.load(f)
|
||||
|
||||
def generate_html_report(results: Dict, output_file: str):
|
||||
"""Generate HTML benchmark report"""
|
||||
|
||||
# Extract data
|
||||
timestamp = datetime.fromtimestamp(results['timestamp'])
|
||||
gpu_info = results['gpu_info']
|
||||
benchmarks = results['benchmarks']
|
||||
|
||||
# Create HTML content
|
||||
html_content = f"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>GPU Benchmark Report - AITBC</title>
|
||||
<style>
|
||||
body {{
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}}
|
||||
.container {{
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}}
|
||||
.header {{
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #007acc;
|
||||
}}
|
||||
.gpu-info {{
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
}}
|
||||
.benchmark-grid {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
margin: 20px 0;
|
||||
}}
|
||||
.benchmark-card {{
|
||||
background: white;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}}
|
||||
.metric {{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 10px 0;
|
||||
}}
|
||||
.metric-label {{
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}}
|
||||
.metric-value {{
|
||||
color: #007acc;
|
||||
font-weight: bold;
|
||||
}}
|
||||
.status-good {{
|
||||
color: #28a745;
|
||||
}}
|
||||
.status-warning {{
|
||||
color: #ffc107;
|
||||
}}
|
||||
.status-bad {{
|
||||
color: #dc3545;
|
||||
}}
|
||||
.chart {{
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}}
|
||||
table {{
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 20px 0;
|
||||
}}
|
||||
th, td {{
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}}
|
||||
th {{
|
||||
background-color: #007acc;
|
||||
color: white;
|
||||
}}
|
||||
.performance-summary {{
|
||||
background: linear-gradient(135deg, #007acc, #0056b3);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🚀 GPU Benchmark Report</h1>
|
||||
<h2>AITBC Performance Analysis</h2>
|
||||
<p>Generated: {timestamp.strftime('%Y-%m-%d %H:%M:%S UTC')}</p>
|
||||
</div>
|
||||
|
||||
<div class="performance-summary">
|
||||
<h3>📊 Performance Summary</h3>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Overall Performance Score:</span>
|
||||
<span class="metric-value">{calculate_performance_score(benchmarks):.1f}/100</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">GPU Utilization:</span>
|
||||
<span class="metric-value">{gpu_info.get('gpu_name', 'Unknown')}</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">CUDA Version:</span>
|
||||
<span class="metric-value">{gpu_info.get('cuda_version', 'N/A')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gpu-info">
|
||||
<h3>🖥️ GPU Information</h3>
|
||||
<table>
|
||||
<tr><th>Property</th><th>Value</th></tr>
|
||||
<tr><td>GPU Name</td><td>{gpu_info.get('gpu_name', 'N/A')}</td></tr>
|
||||
<tr><td>Total Memory</td><td>{gpu_info.get('gpu_memory', 0):.1f} GB</td></tr>
|
||||
<tr><td>Compute Capability</td><td>{gpu_info.get('gpu_compute_capability', 'N/A')}</td></tr>
|
||||
<tr><td>Driver Version</td><td>{gpu_info.get('gpu_driver_version', 'N/A')}</td></tr>
|
||||
<tr><td>Temperature</td><td>{gpu_info.get('gpu_temperature', 'N/A')}°C</td></tr>
|
||||
<tr><td>Power Usage</td><td>{gpu_info.get('gpu_power_usage', 0):.1f}W</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="benchmark-grid">
|
||||
"""
|
||||
|
||||
# Generate benchmark cards
|
||||
for name, data in benchmarks.items():
|
||||
status = get_performance_status(data['ops_per_sec'])
|
||||
html_content += f"""
|
||||
<div class="benchmark-card">
|
||||
<h4>{format_benchmark_name(name)}</h4>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Operations/sec:</span>
|
||||
<span class="metric-value">{data['ops_per_sec']:.2f}</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Mean Time:</span>
|
||||
<span class="metric-value">{data['mean']:.4f}s</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Std Dev:</span>
|
||||
<span class="metric-value">{data['std']:.4f}s</span>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span class="metric-label">Status:</span>
|
||||
<span class="metric-value {status}">{status.replace('_', ' ').title()}</span>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
html_content += """
|
||||
</div>
|
||||
|
||||
<div class="chart">
|
||||
<h3>📈 Performance Comparison</h3>
|
||||
<canvas id="performanceChart" width="800" height="400"></canvas>
|
||||
</div>
|
||||
|
||||
<div class="chart">
|
||||
<h3>🎯 Benchmark Breakdown</h3>
|
||||
<canvas id="breakdownChart" width="800" height="400"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Chart.js implementation would go here
|
||||
// For now, we'll use a simple table representation
|
||||
</script>
|
||||
|
||||
<footer style="margin-top: 40px; text-align: center; color: #666;">
|
||||
<p>AITBC GPU Benchmark Suite v0.2.0</p>
|
||||
<p>Generated automatically by GPU Performance CI</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
# Write HTML file
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(html_content)
|
||||
|
||||
def calculate_performance_score(benchmarks: Dict) -> float:
|
||||
"""Calculate overall performance score (0-100)"""
|
||||
if not benchmarks:
|
||||
return 0.0
|
||||
|
||||
# Weight different benchmark types
|
||||
weights = {
|
||||
'pytorch_matmul': 0.2,
|
||||
'cupy_matmul': 0.2,
|
||||
'gpu_hash_computation': 0.25,
|
||||
'pow_simulation': 0.25,
|
||||
'neural_forward': 0.1
|
||||
}
|
||||
|
||||
total_score = 0.0
|
||||
total_weight = 0.0
|
||||
|
||||
for name, data in benchmarks.items():
|
||||
weight = weights.get(name, 0.1)
|
||||
# Normalize ops/sec to 0-100 scale (arbitrary baseline)
|
||||
normalized_score = min(100, data['ops_per_sec'] / 100) # 100 ops/sec = 100 points
|
||||
total_score += normalized_score * weight
|
||||
total_weight += weight
|
||||
|
||||
return total_score / total_weight if total_weight > 0 else 0.0
|
||||
|
||||
def get_performance_status(ops_per_sec: float) -> str:
|
||||
"""Get performance status based on operations per second"""
|
||||
if ops_per_sec > 100:
|
||||
return "status-good"
|
||||
elif ops_per_sec > 50:
|
||||
return "status-warning"
|
||||
else:
|
||||
return "status-bad"
|
||||
|
||||
def format_benchmark_name(name: str) -> str:
|
||||
"""Format benchmark name for display"""
|
||||
return name.replace('_', ' ').title()
|
||||
|
||||
def compare_with_history(current_results: Dict, history_file: str) -> Dict:
|
||||
"""Compare current results with historical data"""
|
||||
try:
|
||||
with open(history_file, 'r') as f:
|
||||
history = json.load(f)
|
||||
except FileNotFoundError:
|
||||
return {"status": "no_history"}
|
||||
|
||||
# Get most recent historical data
|
||||
if not history.get('results'):
|
||||
return {"status": "no_history"}
|
||||
|
||||
latest_history = history['results'][-1]
|
||||
current_benchmarks = current_results['benchmarks']
|
||||
history_benchmarks = latest_history['benchmarks']
|
||||
|
||||
comparison = {
|
||||
"status": "comparison_available",
|
||||
"timestamp_diff": current_results['timestamp'] - latest_history['timestamp'],
|
||||
"changes": {}
|
||||
}
|
||||
|
||||
for name, current_data in current_benchmarks.items():
|
||||
if name in history_benchmarks:
|
||||
history_data = history_benchmarks[name]
|
||||
change_percent = ((current_data['ops_per_sec'] - history_data['ops_per_sec']) /
|
||||
history_data['ops_per_sec']) * 100
|
||||
|
||||
comparison['changes'][name] = {
|
||||
'current_ops': current_data['ops_per_sec'],
|
||||
'history_ops': history_data['ops_per_sec'],
|
||||
'change_percent': change_percent,
|
||||
'status': 'improved' if change_percent > 5 else 'degraded' if change_percent < -5 else 'stable'
|
||||
}
|
||||
|
||||
return comparison
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Generate GPU benchmark report')
|
||||
parser.add_argument('--input', required=True, help='Input JSON file with benchmark results')
|
||||
parser.add_argument('--output', required=True, help='Output HTML file')
|
||||
parser.add_argument('--history-file', help='Historical benchmark data file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load benchmark results
|
||||
results = load_benchmark_results(args.input)
|
||||
|
||||
# Generate HTML report
|
||||
generate_html_report(results, args.output)
|
||||
|
||||
# Compare with history if available
|
||||
if args.history_file:
|
||||
comparison = compare_with_history(results, args.history_file)
|
||||
print(f"Performance comparison: {comparison['status']}")
|
||||
|
||||
if comparison['status'] == 'comparison_available':
|
||||
for name, change in comparison['changes'].items():
|
||||
print(f"{name}: {change['change_percent']:+.2f}% ({change['status']})")
|
||||
|
||||
print(f"✅ Benchmark report generated: {args.output}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
275
dev/gpu/test_gpu_performance.py
Normal file
275
dev/gpu/test_gpu_performance.py
Normal file
@@ -0,0 +1,275 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
GPU Performance Benchmarking Suite
|
||||
Tests GPU acceleration capabilities for AITBC mining and computation
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import torch
|
||||
import cupy as cp
|
||||
import numpy as np
|
||||
import time
|
||||
import json
|
||||
from typing import Dict, List, Tuple
|
||||
import pynvml
|
||||
|
||||
# Initialize NVML for GPU monitoring
|
||||
try:
|
||||
pynvml.nvmlInit()
|
||||
NVML_AVAILABLE = True
|
||||
except:
|
||||
NVML_AVAILABLE = False
|
||||
|
||||
class GPUBenchmarkSuite:
|
||||
"""Comprehensive GPU benchmarking suite"""
|
||||
|
||||
def __init__(self):
|
||||
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
self.results = {}
|
||||
|
||||
def get_gpu_info(self) -> Dict:
|
||||
"""Get GPU information"""
|
||||
info = {
|
||||
"pytorch_available": torch.cuda.is_available(),
|
||||
"pytorch_version": torch.__version__,
|
||||
"cuda_version": torch.version.cuda if torch.cuda.is_available() else None,
|
||||
"gpu_count": torch.cuda.device_count() if torch.cuda.is_available() else 0,
|
||||
}
|
||||
|
||||
if torch.cuda.is_available():
|
||||
info.update({
|
||||
"gpu_name": torch.cuda.get_device_name(0),
|
||||
"gpu_memory": torch.cuda.get_device_properties(0).total_memory / 1e9,
|
||||
"gpu_compute_capability": torch.cuda.get_device_capability(0),
|
||||
})
|
||||
|
||||
if NVML_AVAILABLE:
|
||||
try:
|
||||
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
|
||||
info.update({
|
||||
"gpu_driver_version": pynvml.nvmlSystemGetDriverVersion().decode(),
|
||||
"gpu_temperature": pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU),
|
||||
"gpu_power_usage": pynvml.nvmlDeviceGetPowerUsage(handle) / 1000, # Watts
|
||||
"gpu_clock": pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_GRAPHICS),
|
||||
})
|
||||
except:
|
||||
pass
|
||||
|
||||
return info
|
||||
|
||||
@pytest.mark.benchmark(group="matrix_operations")
|
||||
def test_matrix_multiplication_pytorch(self, benchmark):
|
||||
"""Benchmark PyTorch matrix multiplication"""
|
||||
if not torch.cuda.is_available():
|
||||
pytest.skip("CUDA not available")
|
||||
|
||||
def matmul_op():
|
||||
size = 2048
|
||||
a = torch.randn(size, size, device=self.device)
|
||||
b = torch.randn(size, size, device=self.device)
|
||||
c = torch.matmul(a, b)
|
||||
return c
|
||||
|
||||
result = benchmark(matmul_op)
|
||||
self.results['pytorch_matmul'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
|
||||
@pytest.mark.benchmark(group="matrix_operations")
|
||||
def test_matrix_multiplication_cupy(self, benchmark):
|
||||
"""Benchmark CuPy matrix multiplication"""
|
||||
try:
|
||||
def matmul_op():
|
||||
size = 2048
|
||||
a = cp.random.randn(size, size, dtype=cp.float32)
|
||||
b = cp.random.randn(size, size, dtype=cp.float32)
|
||||
c = cp.dot(a, b)
|
||||
return c
|
||||
|
||||
result = benchmark(matmul_op)
|
||||
self.results['cupy_matmul'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
except:
|
||||
pytest.skip("CuPy not available")
|
||||
|
||||
@pytest.mark.benchmark(group="mining_operations")
|
||||
def test_hash_computation_gpu(self, benchmark):
|
||||
"""Benchmark GPU hash computation (simulated mining)"""
|
||||
if not torch.cuda.is_available():
|
||||
pytest.skip("CUDA not available")
|
||||
|
||||
def hash_op():
|
||||
# Simulate hash computation workload
|
||||
batch_size = 10000
|
||||
data = torch.randn(batch_size, 32, device=self.device)
|
||||
|
||||
# Simple hash simulation
|
||||
hash_result = torch.sum(data, dim=1)
|
||||
hash_result = torch.abs(hash_result)
|
||||
|
||||
# Additional processing
|
||||
processed = torch.sigmoid(hash_result)
|
||||
return processed
|
||||
|
||||
result = benchmark(hash_op)
|
||||
self.results['gpu_hash_computation'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
|
||||
@pytest.mark.benchmark(group="mining_operations")
|
||||
def test_proof_of_work_simulation(self, benchmark):
|
||||
"""Benchmark proof-of-work simulation"""
|
||||
if not torch.cuda.is_available():
|
||||
pytest.skip("CUDA not available")
|
||||
|
||||
def pow_op():
|
||||
# Simulate PoW computation
|
||||
nonce = torch.randint(0, 2**32, (1000,), device=self.device)
|
||||
data = torch.randn(1000, 64, device=self.device)
|
||||
|
||||
# Hash simulation
|
||||
combined = torch.cat([nonce.float().unsqueeze(1), data], dim=1)
|
||||
hash_result = torch.sum(combined, dim=1)
|
||||
|
||||
# Difficulty check
|
||||
difficulty = torch.tensor(0.001, device=self.device)
|
||||
valid = hash_result < difficulty
|
||||
|
||||
return torch.sum(valid.float()).item()
|
||||
|
||||
result = benchmark(pow_op)
|
||||
self.results['pow_simulation'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
|
||||
@pytest.mark.benchmark(group="neural_operations")
|
||||
def test_neural_network_forward(self, benchmark):
|
||||
"""Benchmark neural network forward pass"""
|
||||
if not torch.cuda.is_available():
|
||||
pytest.skip("CUDA not available")
|
||||
|
||||
# Simple neural network
|
||||
model = torch.nn.Sequential(
|
||||
torch.nn.Linear(784, 256),
|
||||
torch.nn.ReLU(),
|
||||
torch.nn.Linear(256, 128),
|
||||
torch.nn.ReLU(),
|
||||
torch.nn.Linear(128, 10)
|
||||
).to(self.device)
|
||||
|
||||
def forward_op():
|
||||
batch_size = 64
|
||||
x = torch.randn(batch_size, 784, device=self.device)
|
||||
output = model(x)
|
||||
return output
|
||||
|
||||
result = benchmark(forward_op)
|
||||
self.results['neural_forward'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
|
||||
@pytest.mark.benchmark(group="memory_operations")
|
||||
def test_gpu_memory_bandwidth(self, benchmark):
|
||||
"""Benchmark GPU memory bandwidth"""
|
||||
if not torch.cuda.is_available():
|
||||
pytest.skip("CUDA not available")
|
||||
|
||||
def memory_op():
|
||||
size = 100_000_000 # 100M elements
|
||||
# Allocate and copy data
|
||||
a = torch.randn(size, device=self.device)
|
||||
b = torch.randn(size, device=self.device)
|
||||
|
||||
# Memory operations
|
||||
c = a + b
|
||||
d = c * 2.0
|
||||
|
||||
return d
|
||||
|
||||
result = benchmark(memory_op)
|
||||
self.results['memory_bandwidth'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
|
||||
@pytest.mark.benchmark(group="crypto_operations")
|
||||
def test_encryption_operations(self, benchmark):
|
||||
"""Benchmark GPU encryption operations"""
|
||||
if not torch.cuda.is_available():
|
||||
pytest.skip("CUDA not available")
|
||||
|
||||
def encrypt_op():
|
||||
# Simulate encryption workload
|
||||
batch_size = 1000
|
||||
key_size = 256
|
||||
data_size = 1024
|
||||
|
||||
# Generate keys and data
|
||||
keys = torch.randn(batch_size, key_size, device=self.device)
|
||||
data = torch.randn(batch_size, data_size, device=self.device)
|
||||
|
||||
# Simple encryption simulation
|
||||
encrypted = torch.matmul(data, keys.T) / 1000.0
|
||||
decrypted = torch.matmul(encrypted, keys) / 1000.0
|
||||
|
||||
return torch.mean(torch.abs(data - decrypted))
|
||||
|
||||
result = benchmark(encrypt_op)
|
||||
self.results['encryption_ops'] = {
|
||||
'ops_per_sec': 1 / benchmark.stats['mean'],
|
||||
'mean': benchmark.stats['mean'],
|
||||
'std': benchmark.stats['stddev']
|
||||
}
|
||||
return result
|
||||
|
||||
def save_results(self, filename: str):
|
||||
"""Save benchmark results to file"""
|
||||
gpu_info = self.get_gpu_info()
|
||||
|
||||
results_data = {
|
||||
"timestamp": time.time(),
|
||||
"gpu_info": gpu_info,
|
||||
"benchmarks": self.results
|
||||
}
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(results_data, f, indent=2)
|
||||
|
||||
# Test instance
|
||||
benchmark_suite = GPUBenchmarkSuite()
|
||||
|
||||
# Pytest fixture for setup
|
||||
@pytest.fixture(scope="session")
|
||||
def gpu_benchmark():
|
||||
return benchmark_suite
|
||||
|
||||
# Save results after all tests
|
||||
def pytest_sessionfinish(session, exitstatus):
|
||||
"""Save benchmark results after test completion"""
|
||||
try:
|
||||
benchmark_suite.save_results('gpu_benchmark_results.json')
|
||||
except Exception as e:
|
||||
print(f"Failed to save benchmark results: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run benchmarks directly
|
||||
import sys
|
||||
sys.exit(pytest.main([__file__, "-v", "--benchmark-only"]))
|
||||
Reference in New Issue
Block a user