forked from masonhuang/cluster4npu
feat: integrate Phase 1-4 components into main dashboard
- Performance tab: add PerformanceDashboard live stats widget - Performance tab: add Benchmark button (opens BenchmarkDialog) - Performance tab: add Export Report button (opens ExportReportDialog) - Dongles tab: embed DeviceManagementPanel with 3s auto-refresh - Fix pipeline_config type: analyze_pipeline_stages returns List not Dict All integrations are guarded with try/except and AVAILABLE flags to prevent import errors from breaking existing functionality. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
55040733fe
commit
d2fdbf85ee
@ -59,6 +59,25 @@ from core.nodes.exact_nodes import (
|
||||
ExactPostprocessNode, ExactOutputNode, EXACT_NODE_TYPES
|
||||
)
|
||||
|
||||
try:
|
||||
from ui.components.performance_dashboard import PerformanceDashboard
|
||||
PERFORMANCE_DASHBOARD_AVAILABLE = True
|
||||
except ImportError:
|
||||
PERFORMANCE_DASHBOARD_AVAILABLE = False
|
||||
|
||||
try:
|
||||
from ui.components.device_management_panel import DeviceManagementPanel
|
||||
from core.device.device_manager import DeviceManager
|
||||
DEVICE_MANAGEMENT_AVAILABLE = True
|
||||
except ImportError:
|
||||
DEVICE_MANAGEMENT_AVAILABLE = False
|
||||
|
||||
try:
|
||||
from ui.dialogs.export_report_dialog import ExportReportDialog
|
||||
EXPORT_REPORT_AVAILABLE = True
|
||||
except ImportError:
|
||||
EXPORT_REPORT_AVAILABLE = False
|
||||
|
||||
# Import pipeline analysis functions
|
||||
try:
|
||||
from core.pipeline import get_stage_count, analyze_pipeline_stages, get_pipeline_summary
|
||||
@ -158,6 +177,8 @@ class IntegratedPipelineDashboard(QMainWindow):
|
||||
self.props_instructions = None
|
||||
self.node_props_container = None
|
||||
self.node_props_layout = None
|
||||
self.device_manager = None
|
||||
self.device_management_panel = None
|
||||
self.fps_label = None
|
||||
self.latency_label = None
|
||||
self.memory_label = None
|
||||
@ -895,7 +916,20 @@ class IntegratedPipelineDashboard(QMainWindow):
|
||||
metrics_layout.addRow("Memory Usage:", self.memory_label)
|
||||
|
||||
layout.addWidget(metrics_group)
|
||||
|
||||
|
||||
# Real-time performance monitor
|
||||
perf_dashboard_group = QGroupBox("即時效能監控")
|
||||
perf_dashboard_layout = QVBoxLayout(perf_dashboard_group)
|
||||
if PERFORMANCE_DASHBOARD_AVAILABLE:
|
||||
self.performance_dashboard = PerformanceDashboard()
|
||||
else:
|
||||
self.performance_dashboard = None
|
||||
if self.performance_dashboard:
|
||||
perf_dashboard_layout.addWidget(self.performance_dashboard)
|
||||
else:
|
||||
perf_dashboard_layout.addWidget(QLabel("PerformanceDashboard 不可用"))
|
||||
layout.addWidget(perf_dashboard_group)
|
||||
|
||||
# Suggestions
|
||||
suggestions_group = QGroupBox("Optimization Suggestions")
|
||||
suggestions_layout = QVBoxLayout(suggestions_group)
|
||||
@ -907,6 +941,26 @@ class IntegratedPipelineDashboard(QMainWindow):
|
||||
|
||||
layout.addWidget(suggestions_group)
|
||||
|
||||
# Benchmark section
|
||||
benchmark_group = QGroupBox("效能 Benchmark")
|
||||
benchmark_layout = QVBoxLayout(benchmark_group)
|
||||
|
||||
self.benchmark_button = QPushButton("執行 Benchmark")
|
||||
self.benchmark_button.setToolTip("比較單 Dongle vs 多 Dongle 的效能差異")
|
||||
self.benchmark_button.clicked.connect(self.open_benchmark_dialog)
|
||||
benchmark_layout.addWidget(self.benchmark_button)
|
||||
|
||||
layout.addWidget(benchmark_group)
|
||||
|
||||
if EXPORT_REPORT_AVAILABLE:
|
||||
export_group = QGroupBox("報告匯出")
|
||||
export_layout = QVBoxLayout(export_group)
|
||||
self.export_report_button = QPushButton("匯出效能報告(PDF/CSV)")
|
||||
self.export_report_button.setToolTip("將 Benchmark 結果與歷史記錄匯出為 PDF 或 CSV")
|
||||
self.export_report_button.clicked.connect(self.open_export_report_dialog)
|
||||
export_layout.addWidget(self.export_report_button)
|
||||
layout.addWidget(export_group)
|
||||
|
||||
# Deploy section
|
||||
deploy_group = QGroupBox("Pipeline Deployment")
|
||||
deploy_layout = QVBoxLayout(deploy_group)
|
||||
@ -977,12 +1031,23 @@ class IntegratedPipelineDashboard(QMainWindow):
|
||||
self.dongles_list.addItem("No dongles detected. Click 'Detect Dongles' to scan.")
|
||||
layout.addWidget(self.dongles_list)
|
||||
|
||||
if DEVICE_MANAGEMENT_AVAILABLE:
|
||||
try:
|
||||
self.device_manager = DeviceManager()
|
||||
self.device_management_panel = DeviceManagementPanel(self.device_manager)
|
||||
self.device_management_panel.set_auto_refresh(3000)
|
||||
layout.addWidget(self.device_management_panel)
|
||||
except Exception as e:
|
||||
err_label = QLabel(f"裝置管理面板初始化失敗:{e}")
|
||||
err_label.setStyleSheet("color: #f38ba8; font-size: 11px;")
|
||||
layout.addWidget(err_label)
|
||||
|
||||
layout.addStretch()
|
||||
widget.setWidget(content)
|
||||
widget.setWidgetResizable(True)
|
||||
|
||||
|
||||
return widget
|
||||
|
||||
|
||||
def setup_menu(self):
|
||||
"""Setup the menu bar."""
|
||||
menubar = self.menuBar()
|
||||
@ -1925,7 +1990,58 @@ class IntegratedPipelineDashboard(QMainWindow):
|
||||
suggestions.append("Pipeline configuration looks good for optimal performance.")
|
||||
|
||||
self.suggestions_text.setPlainText("\n".join(suggestions))
|
||||
|
||||
|
||||
# Update PerformanceDashboard (if available)
|
||||
if hasattr(self, 'performance_dashboard') and self.performance_dashboard:
|
||||
self.performance_dashboard.update_stats({
|
||||
"fps": float(estimated_fps),
|
||||
"avg_latency_ms": float(estimated_latency),
|
||||
"p95_latency_ms": float(estimated_latency * 1.5) # 估算 p95
|
||||
})
|
||||
|
||||
def open_benchmark_dialog(self):
|
||||
"""開啟 Benchmark 對話框。"""
|
||||
try:
|
||||
from ui.dialogs.benchmark_dialog import BenchmarkDialog
|
||||
from core.pipeline import analyze_pipeline_stages
|
||||
|
||||
if not self.graph:
|
||||
QMessageBox.warning(self, "無 Pipeline", "請先建立 Pipeline 再執行 Benchmark。")
|
||||
return
|
||||
|
||||
stages = analyze_pipeline_stages(self.graph)
|
||||
# analyze_pipeline_stages 回傳 List[PipelineStage]
|
||||
pipeline_config = stages if stages else []
|
||||
|
||||
dialog = BenchmarkDialog(self, pipeline_config)
|
||||
dialog.exec_()
|
||||
except ImportError as e:
|
||||
QMessageBox.warning(self, "功能未啟用", f"Benchmark 功能暫不可用:{e}")
|
||||
|
||||
def open_export_report_dialog(self):
|
||||
"""開啟效能報告匯出對話框。"""
|
||||
try:
|
||||
from ui.dialogs.export_report_dialog import ExportReportDialog
|
||||
from core.performance.benchmarker import PerformanceBenchmarker
|
||||
from core.performance.history import PerformanceHistory
|
||||
from core.device.device_manager import DeviceManager
|
||||
|
||||
benchmarker = getattr(self, '_benchmarker', None)
|
||||
history = getattr(self, '_perf_history', None)
|
||||
device_manager = getattr(self, 'device_manager', None)
|
||||
dashboard = getattr(self, 'performance_dashboard', None)
|
||||
|
||||
dialog = ExportReportDialog(
|
||||
parent=self,
|
||||
benchmarker=benchmarker,
|
||||
history=history,
|
||||
device_manager=device_manager,
|
||||
dashboard=dashboard,
|
||||
)
|
||||
dialog.exec_()
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "匯出功能", f"無法開啟報告匯出:{e}")
|
||||
|
||||
def delete_selected_nodes(self):
|
||||
"""Delete selected nodes from the graph."""
|
||||
if not self.graph:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user