增加L0训练阶段的MCTS部分

This commit is contained in:
hisatri
2025-07-23 07:04:10 +08:00
parent 88bed2a1ef
commit 4410defbe5
23 changed files with 5205 additions and 0 deletions

356
tools/benchmark.py Normal file
View File

@@ -0,0 +1,356 @@
"""
Deep2048 快速基准测试工具
自动测试不同配置的性能,找出最优的线程数和参数设置
"""
import time
import torch
import multiprocessing as mp
from typing import Dict, List, Tuple, Optional
import json
from pathlib import Path
import argparse
from game import Game2048
from mcts import PureMCTS
from training_data import TrainingDataManager
class QuickBenchmark:
"""快速基准测试工具"""
def __init__(self, output_dir: str = "results/benchmark"):
"""
初始化基准测试
Args:
output_dir: 结果输出目录
"""
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
# 系统信息
self.cpu_count = mp.cpu_count()
self.cuda_available = torch.cuda.is_available()
print(f"系统信息:")
print(f" CPU核心数: {self.cpu_count}")
print(f" CUDA可用: {self.cuda_available}")
if self.cuda_available:
print(f" CUDA设备: {torch.cuda.get_device_name()}")
def test_thread_performance(self, simulations: int = 200) -> Dict[int, Dict]:
"""
测试不同线程数的性能
Args:
simulations: 每次测试的模拟次数
Returns:
线程数 -> 性能指标的字典
"""
print(f"\n=== 线程性能测试 ({simulations} 模拟) ===")
# 测试的线程数配置
thread_configs = [1, 2, 4]
if self.cpu_count >= 8:
thread_configs.append(8)
if self.cpu_count >= 16:
thread_configs.append(16)
results = {}
for num_threads in thread_configs:
print(f"\n测试 {num_threads} 线程...")
# 创建MCTS
mcts = PureMCTS(
c_param=1.414,
max_simulation_depth=80,
num_threads=num_threads
)
# 运行多次测试取平均值
times = []
scores = []
for run in range(3): # 3次运行
game = Game2048(height=3, width=3, seed=42 + run)
start_time = time.time()
best_action, root = mcts.search(game, simulations)
elapsed_time = time.time() - start_time
times.append(elapsed_time)
if root:
# 计算平均子节点价值作为质量指标
avg_value = sum(child.average_value for child in root.children.values()) / len(root.children) if root.children else 0
scores.append(avg_value)
else:
scores.append(0)
# 计算统计指标
avg_time = sum(times) / len(times)
avg_score = sum(scores) / len(scores)
sims_per_sec = simulations / avg_time
# 计算效率(每核心每秒模拟数)
efficiency = sims_per_sec / num_threads
# 计算相对于单线程的加速比
if num_threads == 1:
baseline_speed = sims_per_sec
speedup = 1.0
else:
speedup = sims_per_sec / baseline_speed if 'baseline_speed' in locals() else 1.0
results[num_threads] = {
'avg_time': avg_time,
'sims_per_sec': sims_per_sec,
'efficiency': efficiency,
'speedup': speedup,
'avg_score': avg_score,
'times': times
}
print(f" 平均时间: {avg_time:.3f}")
print(f" 模拟速度: {sims_per_sec:.1f} 次/秒")
print(f" 效率: {efficiency:.1f} 模拟/秒/核心")
print(f" 加速比: {speedup:.2f}x")
return results
def test_simulation_depth(self, num_threads: int = None) -> Dict[int, Dict]:
"""
测试不同模拟深度的影响
Args:
num_threads: 线程数None表示使用最优线程数
Returns:
深度 -> 性能指标的字典
"""
if num_threads is None:
num_threads = min(4, self.cpu_count)
print(f"\n=== 模拟深度测试 ({num_threads} 线程) ===")
depths = [50, 80, 120, 200]
results = {}
for depth in depths:
print(f"\n测试深度 {depth}...")
mcts = PureMCTS(
c_param=1.414,
max_simulation_depth=depth,
num_threads=num_threads
)
game = Game2048(height=3, width=3, seed=42)
start_time = time.time()
best_action, root = mcts.search(game, 150) # 固定模拟次数
elapsed_time = time.time() - start_time
sims_per_sec = 150 / elapsed_time
avg_value = sum(child.average_value for child in root.children.values()) / len(root.children) if root and root.children else 0
results[depth] = {
'time': elapsed_time,
'sims_per_sec': sims_per_sec,
'avg_value': avg_value
}
print(f" 时间: {elapsed_time:.3f}")
print(f" 速度: {sims_per_sec:.1f} 次/秒")
print(f" 平均价值: {avg_value:.1f}")
return results
def test_board_sizes(self, num_threads: int = None) -> Dict[str, Dict]:
"""
测试不同棋盘大小的性能
Args:
num_threads: 线程数
Returns:
棋盘大小 -> 性能指标的字典
"""
if num_threads is None:
num_threads = min(4, self.cpu_count)
print(f"\n=== 棋盘大小测试 ({num_threads} 线程) ===")
board_sizes = [(3, 3), (4, 4), (3, 4), (4, 3)]
results = {}
for height, width in board_sizes:
size_key = f"{height}x{width}"
print(f"\n测试 {size_key} 棋盘...")
mcts = PureMCTS(
c_param=1.414,
max_simulation_depth=80,
num_threads=num_threads
)
game = Game2048(height=height, width=width, seed=42)
start_time = time.time()
best_action, root = mcts.search(game, 100)
elapsed_time = time.time() - start_time
sims_per_sec = 100 / elapsed_time
valid_moves = len(game.get_valid_moves())
results[size_key] = {
'time': elapsed_time,
'sims_per_sec': sims_per_sec,
'valid_moves': valid_moves,
'board_cells': height * width
}
print(f" 时间: {elapsed_time:.3f}")
print(f" 速度: {sims_per_sec:.1f} 次/秒")
print(f" 有效动作: {valid_moves}")
return results
def find_optimal_config(self) -> Dict:
"""
找到最优配置
Returns:
最优配置字典
"""
print("\n=== 寻找最优配置 ===")
# 测试线程性能
thread_results = self.test_thread_performance(200)
# 找到最优线程数(基于效率和绝对速度的平衡)
best_thread_score = 0
best_threads = 1
for threads, result in thread_results.items():
# 综合评分:速度 * 0.7 + 效率 * 0.3
score = result['sims_per_sec'] * 0.7 + result['efficiency'] * 0.3
if score > best_thread_score:
best_thread_score = score
best_threads = threads
print(f"\n最优线程数: {best_threads}")
print(f" 速度: {thread_results[best_threads]['sims_per_sec']:.1f} 模拟/秒")
print(f" 效率: {thread_results[best_threads]['efficiency']:.1f} 模拟/秒/核心")
print(f" 加速比: {thread_results[best_threads]['speedup']:.2f}x")
# 测试其他参数
depth_results = self.test_simulation_depth(best_threads)
board_results = self.test_board_sizes(best_threads)
# 推荐配置
optimal_config = {
'recommended_threads': best_threads,
'recommended_depth': 80, # 平衡性能和质量
'recommended_board_size': (3, 3), # L0阶段推荐
'performance_summary': {
'best_speed': thread_results[best_threads]['sims_per_sec'],
'best_efficiency': thread_results[best_threads]['efficiency'],
'speedup': thread_results[best_threads]['speedup']
},
'system_info': {
'cpu_cores': self.cpu_count,
'cuda_available': self.cuda_available
}
}
return optimal_config
def run_full_benchmark(self) -> Dict:
"""运行完整基准测试"""
print("Deep2048 快速基准测试")
print("=" * 50)
start_time = time.time()
# 运行所有测试
results = {
'timestamp': time.time(),
'system_info': {
'cpu_cores': self.cpu_count,
'cuda_available': self.cuda_available
},
'thread_performance': self.test_thread_performance(200),
'optimal_config': self.find_optimal_config()
}
total_time = time.time() - start_time
results['benchmark_time'] = total_time
# 保存结果
result_file = self.output_dir / f"benchmark_results_{int(time.time())}.json"
with open(result_file, 'w', encoding='utf-8') as f:
json.dump(results, f, indent=2, ensure_ascii=False)
print(f"\n基准测试完成! 用时: {total_time:.1f}")
print(f"结果已保存到: {result_file}")
return results
def print_recommendations(self, results: Dict):
"""打印配置推荐"""
config = results['optimal_config']
print("\n" + "=" * 50)
print("🚀 性能优化推荐")
print("=" * 50)
print(f"推荐线程数: {config['recommended_threads']}")
print(f"推荐模拟深度: {config['recommended_depth']}")
print(f"推荐棋盘大小: {config['recommended_board_size']}")
print(f"\n预期性能:")
print(f" 模拟速度: {config['performance_summary']['best_speed']:.1f} 次/秒")
print(f" CPU效率: {config['performance_summary']['best_efficiency']:.1f} 模拟/秒/核心")
print(f" 多线程加速: {config['performance_summary']['speedup']:.2f}x")
print(f"\n配置示例:")
print(f"```python")
print(f"mcts = PureMCTS(")
print(f" c_param=1.414,")
print(f" max_simulation_depth={config['recommended_depth']},")
print(f" num_threads={config['recommended_threads']}")
print(f")")
print(f"```")
def main():
"""主函数"""
parser = argparse.ArgumentParser(description="Deep2048快速基准测试")
parser.add_argument("--output", "-o", default="results/benchmark", help="输出目录")
parser.add_argument("--quick", action="store_true", help="快速测试模式")
args = parser.parse_args()
benchmark = QuickBenchmark(args.output)
if args.quick:
# 快速测试模式
print("快速测试模式")
thread_results = benchmark.test_thread_performance(100)
# 简单推荐
best_threads = max(thread_results.keys(), key=lambda k: thread_results[k]['sims_per_sec'])
print(f"\n快速推荐: 使用 {best_threads} 线程")
print(f"预期速度: {thread_results[best_threads]['sims_per_sec']:.1f} 模拟/秒")
else:
# 完整基准测试
results = benchmark.run_full_benchmark()
benchmark.print_recommendations(results)
if __name__ == "__main__":
main()