🤖 AI 资讯

· · ↗
← 返回列表

[云计算] [数据分享] 基于 ISLP 负载实测: OCI Ampere A1 (ARM64)、Kaggle、Lightning 与本地 6800H 多线程性能对比

V2EX2026-11-01 01:56:07大模型,算力芯片,政策监管,Meta,NVIDIA,教育学习,模型评测,模型安全对齐,招聘HR,榜单评测原文 ↗

跑《统计学习导论》(ISLP) 实验时,顺手测了一下常用免费云端算力实例与本地标压笔记本在基础机器学习负载下的性能差异。非严格学术评测,仅记录单机工程数据供参考

一、 测试环境

  • OCI ARM:Ampere Altra 架构,4 OCPU (独立物理核),24 GB RAM ,Ubuntu 22.04

  • Lightning AI:Free CPU Studio ( 4 vCPU 共享容器)

  • Kaggle:标准 CPU 实例( 4 vCPU )及 Tesla T4 GPU 实例

  • Local:AMD Ryzen 7 6800H ( 8 核 16 线程)+ RTX 3050 Laptop (4GB VRAM)


二、 基准测试数据

1. scikit-learn:随机森林分类( CPU )
  • 数据规格:合成二分类数据集,40,000 样本,40 特征,200 棵树( 32k 训练 / 8k 测试),random_state=42。全平台测试集准确率均为 95.59%
并行任务数 (n_jobs) OCI ARM (Ampere) Lightning CPU Kaggle CPU Ryzen 7 6800H (本地)
1 34.12 s

| 28.34 s

| 70.88 s

| 27.63 s

| | 2 | 17.74 s

| 15.54 s

| 36.97 s

| 14.12 s

| | 4 | 9.50 s

| 11.13 s

| 24.79 s

| 7.43 s

| | 8 | — | — | — | 4.50 s

| | 16 | — | — | — | 3.04 s

|

注:Kaggle CPU 在 4 线程时表现出较明显的扩展瓶颈,耗时为本地 6800H 的 3.3 倍; OCI ARM 在 1 核至 4 核间表现出接近线性的加速比(约 3.59x )

2. PyTorch:CPU 矩阵乘法( 4096×4096 ,float32 )
  • 测试逻辑:torch.set_num_interop_threads(1),显式预热,多次采样取中位数耗时
线程数 (threads) OCI ARM (Ampere) Lightning CPU Kaggle CPU Ryzen 7 6800H (本地)
1 3.66 s (37.5 GFLOP/s)

| 0.90 s

| 2.03 s

| 1.20 s

| | 2 | 1.85 s (74.3 GFLOP/s)

| 0.48 s

| 1.05 s

| 0.64 s

| | 4 | 1.06 s (129.9 GFLOP/s)

| 0.93 s

| 1.02 s

| 0.44 s

| | 8 | — | — | — | 0.27 s

| | 16 | — | — | — | 0.24 s

|

注:Lightning CPU 在 1~2 线程下受益于 x86 高级矢量扩展(AVX)及底层优化的数学库,单核吞吐占优,但打满 4 线程时收益见顶; OCI ARM 多核扩展曲线相对平稳

3. GPU 单算子基准参照( 4096×4096 Matmul )
  • 参数设定:PyTorch float32 ,显式关闭 TF32 ,包含 torch.cuda.synchronize() 同步
硬件平台 单次中位数耗时 计算吞吐
Ryzen 7 6800H (16 线程 CPU) 236.80 ms

| ~580 GFLOP/s | | Kaggle Tesla T4 (16GB VRAM) | 40.86 ms

| ~3363 GFLOP/s | | 本地 RTX 3050 Laptop (4GB VRAM) | 36.91 ms

| ~3723 GFLOP/s |

注:纯单算子吞吐下移动端 3050 略胜 T4 ,但 4GB 显存无法承载大规模上下文与 Batch Size ,仅适用于小模型原型快速验证


三、 观察与局限

  1. 物理核 vs 容器超卖: Kaggle 与 Lightning 的 4 vCPU 在高并发下扩展性衰减,推测主要受宿主机多租户超卖导致的上下文切换(Context Switch)及 CPU 配额(Quota)节流限制; OCI ARM 绑定的为独立物理核心,扩展曲线受多租户干扰相对较小

  2. 测试局限: 各实例未强制对齐底层线性代数库与依赖环境(如 OpenBLAS / MKL 编译后端差异),随机森林单次采样可能存在瞬态扰动

四、源码

import importlib.metadata as metadata import os import platform import statistics import sys import time

import numpy as np import sklearn import torch from joblib import cpu_count from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split

ORACLE_RF_SECONDS = {1: 34.124, 2: 17.737, 4: 9.503} ORACLE_TORCH_CPU_SECONDS = { 1024: {1: 0.0571, 2: 0.0293, 4: 0.0158}, 2048: {1: 0.4531, 2: 0.2266, 4: 0.1237}, 4096: {1: 3.6563, 2: 1.8504, 4: 1.0573}, } OFFICIAL_TARGETS = { "numpy": "2.3.5", "scipy": "1.16.3", "scikit-learn": "1.8.0", "ISLP": "0.4.1", "torch": "2.10.0", }

def installed_version(name): try: return metadata.version(name) except metadata.PackageNotFoundError: return "未安装"

def environment_report(): print("=" * 72) print("环境检查") print("=" * 72) print(f"OS / 架构 : {platform.platform()} / {platform.machine()}") print(f"Python : {sys.version.split()[0]}") print(f"逻辑 CPU ( OS ) : {os.cpu_count()}") print(f"可用 CPU ( joblib ) : {cpu_count()}") print(f"PyTorch : {torch.version}") print(f"PyTorch 默认线程数 : {torch.get_num_threads()}") print(f"CUDA 可用 : {torch.cuda.is_available()}") if torch.cuda.is_available(): print(f"GPU : {torch.cuda.get_device_name(0)}") print("\nISLP_labs v2.2.2 官方 requirements 相关目标版本:") for package, target in OFFICIAL_TARGETS.items(): actual = installed_version(package) print(f" {package:16} 当前={actual:18} 目标={target}") print("提示:先记录平台预装版本。不要只为版本号相同就替换 Kaggle 预装的 PyTorch ;这可能影响 GPU/CUDA 配置。") print("线程数 1/2/4 用于与 Oracle 的结果横向比较;若平台可用 CPU 少于 4 ,4 线程结果可能受资源限制。")

def random_forest_benchmark(): print("\n" + "=" * 72) print("任务 A:scikit-learn 随机森林( CPU )") print("=" * 72) print("数据:40,000 个样本、40 个特征;训练集 32,000 ,测试集 8,000 ; 200 棵树。") data_start = time.perf_counter() X, y = make_classification( n_samples=40_000, n_features=40, n_informative=20, n_redundant=10, n_classes=2, random_state=42, ) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) print(f"数据准备耗时:{time.perf_counter() - data_start:.3f} 秒") results = [] for n_jobs in (1, 2, 4): model = RandomForestClassifier( n_estimators=200, max_features="sqrt", random_state=42, n_jobs=n_jobs ) t0 = time.perf_counter() model.fit(X_train, y_train) train_seconds = time.perf_counter() - t0 t0 = time.perf_counter() pred = model.predict(X_test) predict_seconds = time.perf_counter() - t0 accuracy = accuracy_score(y_test, pred) results.append((n_jobs, train_seconds, predict_seconds, accuracy)) print(f"\nn_jobs={n_jobs}: 训练 {train_seconds:.3f}s | 预测 {predict_seconds:.3f}s | 准确率 {accuracy:.4%}") baseline = results[0][1] print("\n 与 Oracle 同一任务实测对比(训练时间):") for n_jobs, seconds, predict_seconds, accuracy in results: oracle = ORACLE_RF_SECONDS[n_jobs] if seconds > 0: ratio = oracle / seconds label = f"Kaggle 约快 {ratio:.2f} 倍" if ratio > 1.01 else (f"Oracle 约快 {1/ratio:.2f} 倍" if ratio < 0.99 else "两者接近") else: label = "无法计算比例" print(f"{n_jobs} 线程 | Kaggle {seconds:.3f}s | Oracle {oracle:.3f}s | {label} | 加速 {baseline/seconds:.2f}x") return results

def pytorch_cpu_benchmark(): print("\n" + "=" * 72) print("任务 B:PyTorch CPU 矩阵乘法(与 Oracle 使用相同矩阵规模)") print("=" * 72) print("dtype=float32 ;只测 CPU ;每轮使用中位数,包含一次预热但不计入耗时。") torch.manual_seed(42) torch.set_num_interop_threads(1) all_results = {} for n in (1024, 2048, 4096): print(f"\n 矩阵:{n} × {n}") a = torch.randn(n, n, dtype=torch.float32, device="cpu") b = torch.randn(n, n, dtype=torch.float32, device="cpu") repeats = 5 if n == 1024 else (3 if n == 2048 else 2) all_results[n] = {} for threads in (1, 2, 4): torch.set_num_threads(threads) _ = a @ b # 预热 samples = [] for _ in range(repeats): t0 = time.perf_counter() c = a @ b samples.append(time.perf_counter() - t0) del c seconds = statistics.median(samples) gflops = (2 * n**3) / seconds / 1e9 all_results[n][threads] = seconds oracle = ORACLE_TORCH_CPU_SECONDS[n][threads] if seconds > 0: ratio = oracle / seconds label = f"Kaggle 约快 {ratio:.2f} 倍" if ratio > 1.01 else (f"Oracle 约快 {1/ratio:.2f} 倍" if ratio < 0.99 else "两者接近") else: label = "无法计算比例" print(f"threads={threads} | 中位数 {seconds1000:.1f} ms | {gflops:.2f} GFLOP/s | Oracle {oracle1000:.1f} ms | {label}") del a, b return all_results

def pytorch_gpu_benchmark(): print("\n" + "=" * 72) print("任务 C:PyTorch GPU 矩阵乘法(仅当 CUDA 可用时运行)") print("=" * 72) if not torch.cuda.is_available(): print("跳过:torch.cuda.is_available() 为 False 。若想测试 Kaggle GPU ,请在 Notebook 的 Settings / Accelerator 中选择 GPU 后重启会话。") return device = torch.device("cuda") print(f"GPU:{torch.cuda.get_d