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
|
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
|
# Import pipeline analysis functions
|
||||||
try:
|
try:
|
||||||
from core.pipeline import get_stage_count, analyze_pipeline_stages, get_pipeline_summary
|
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.props_instructions = None
|
||||||
self.node_props_container = None
|
self.node_props_container = None
|
||||||
self.node_props_layout = None
|
self.node_props_layout = None
|
||||||
|
self.device_manager = None
|
||||||
|
self.device_management_panel = None
|
||||||
self.fps_label = None
|
self.fps_label = None
|
||||||
self.latency_label = None
|
self.latency_label = None
|
||||||
self.memory_label = None
|
self.memory_label = None
|
||||||
@ -895,7 +916,20 @@ class IntegratedPipelineDashboard(QMainWindow):
|
|||||||
metrics_layout.addRow("Memory Usage:", self.memory_label)
|
metrics_layout.addRow("Memory Usage:", self.memory_label)
|
||||||
|
|
||||||
layout.addWidget(metrics_group)
|
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
|
||||||
suggestions_group = QGroupBox("Optimization Suggestions")
|
suggestions_group = QGroupBox("Optimization Suggestions")
|
||||||
suggestions_layout = QVBoxLayout(suggestions_group)
|
suggestions_layout = QVBoxLayout(suggestions_group)
|
||||||
@ -907,6 +941,26 @@ class IntegratedPipelineDashboard(QMainWindow):
|
|||||||
|
|
||||||
layout.addWidget(suggestions_group)
|
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 section
|
||||||
deploy_group = QGroupBox("Pipeline Deployment")
|
deploy_group = QGroupBox("Pipeline Deployment")
|
||||||
deploy_layout = QVBoxLayout(deploy_group)
|
deploy_layout = QVBoxLayout(deploy_group)
|
||||||
@ -977,12 +1031,23 @@ class IntegratedPipelineDashboard(QMainWindow):
|
|||||||
self.dongles_list.addItem("No dongles detected. Click 'Detect Dongles' to scan.")
|
self.dongles_list.addItem("No dongles detected. Click 'Detect Dongles' to scan.")
|
||||||
layout.addWidget(self.dongles_list)
|
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()
|
layout.addStretch()
|
||||||
widget.setWidget(content)
|
widget.setWidget(content)
|
||||||
widget.setWidgetResizable(True)
|
widget.setWidgetResizable(True)
|
||||||
|
|
||||||
return widget
|
return widget
|
||||||
|
|
||||||
def setup_menu(self):
|
def setup_menu(self):
|
||||||
"""Setup the menu bar."""
|
"""Setup the menu bar."""
|
||||||
menubar = self.menuBar()
|
menubar = self.menuBar()
|
||||||
@ -1925,7 +1990,58 @@ class IntegratedPipelineDashboard(QMainWindow):
|
|||||||
suggestions.append("Pipeline configuration looks good for optimal performance.")
|
suggestions.append("Pipeline configuration looks good for optimal performance.")
|
||||||
|
|
||||||
self.suggestions_text.setPlainText("\n".join(suggestions))
|
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):
|
def delete_selected_nodes(self):
|
||||||
"""Delete selected nodes from the graph."""
|
"""Delete selected nodes from the graph."""
|
||||||
if not self.graph:
|
if not self.graph:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user