Skip to content

Commit 7a1e05e

Browse files
SAKURA-CATkites262
andauthored
refactor: new data model (#748)
Co-authored-by: kites262 <[email protected]>
1 parent c02471a commit 7a1e05e

File tree

27 files changed

+900
-492
lines changed

27 files changed

+900
-492
lines changed

docs/实验元数据.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# 实验元数据
2+
3+
> ⚠️ 自**0.3.26**版本开始,swanlab对硬件部分元数据进行调整,旧版数据依旧会在前端做向下兼容展示,但是不会再维护。
4+
> 请试用最新的版本,以获得最佳的体验。
5+
6+
在每次实验开启时,也就是您执行`swanlab.init`函数时,swanlab默认将采集有关**当前工作目录**下的相关信息,以及当前计算机的硬件信息,作为实验元数据,与实验信息记录在一起。
7+
本部分将介绍swanlab在每一次实验中记录的元数据信息,包括计算机信息、git信息等。由于历史版本原因并考虑向下兼容性,本部分元信息字段被展平而没有使用嵌套结构,可能会加重一些阅读成本。
8+
不过大致上,我们将元数据分为三个类别:硬件信息、运行时信息、环境依赖信息。
9+
10+
这部分代码存储在[metadata](/swanlab/data/run/metadata)目录下。
11+
12+
## 硬件信息
13+
14+
有时候硬件信息直接决定了实验的运行、计算效率,我们将采集您的计算机的硬件信息,帮助您评估训练模型性能,他们包括:
15+
16+
1. CPU信息:品牌、核心数等
17+
2. GPU信息:品牌(制造商)、型号、显存等
18+
3. NPU信息:swanlab支持[华为昇腾AI处理器](https://e.huawei.com/cn/products/computing/ascend)的信息采集
19+
4. SOC信息:swanlab也支持苹果m系列芯片的信息采集
20+
5. 内存信息
21+
22+
于此同时,[硬件监控](/docs/硬件监控.md)的功能实现依赖于实验元数据的监测,因为我们不可能每次监控时都重新检测系统的所有硬件信息,
23+
实际上在swanlab初始化时如何监控、监控哪些硬件信息是已经完全确定的,我们只需要在上下文中保存这些信息即可(在实际代码中,您将看到是一个个函数)。
24+
25+
## 运行时信息
26+
27+
运行时信息偏软件,他们大致包含:
28+
29+
1. 操作系统信息
30+
2. git信息
31+
3. python解释器信息
32+
33+
### 操作系统信息
34+
35+
swanlab将采集当前计算机的操作系统信息,包括操作系统型号、版本、主机名等:
36+
37+
```python
38+
import platform
39+
import socket
40+
import os
41+
def get_computer_info():
42+
return {
43+
"os": platform.platform(),
44+
"hostname": socket.gethostname(),
45+
"pid": os.getpid(),
46+
"cwd": os.getcwd(),
47+
}
48+
```
49+
50+
### git信息
51+
52+
如果当前工作目录是一个git仓库,swanlab将通过`subprocess`采集git信息,包括当前分支、commit id等,例如:
53+
54+
```python
55+
import subprocess
56+
branch_process = subprocess.Popen(
57+
["git", "branch", "--show-current"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
58+
)
59+
```
60+
61+
我们暂时并没有通过第三方库例如[GitPython](https://github.com/gitpython-developers/GitPython)等来获取git信息,因为我们只用到一些比较简单的信息,而且这样可以减少依赖。
62+
63+
64+
### python解释器信息
65+
66+
python的解释器信息被保存在`sys``platform`标准库中,很容易获取到:
67+
68+
```python
69+
import platform
70+
import sys
71+
def get_python_info():
72+
return {
73+
"python": platform.python_version(),
74+
"python_verbose": sys.version,
75+
"executable": sys.executable,
76+
"command": " ".join(sys.argv),
77+
}
78+
```
79+
80+
## 环境依赖信息
81+
82+
环境依赖信息是指当前python环境下的依赖包信息,我们将采集当前环墶下的所有依赖包信息,包括包名、版本等:
83+
84+
```python
85+
import subprocess
86+
87+
result = subprocess.run(["pip", "list", "--format=freeze"], stdout=subprocess.PIPE, text=True)
88+
```
89+
这是一个纯本文的输出,swanlab将直接保存它。
90+
91+
## 其他
92+
93+
### 第三方信息
94+
95+
swanlab作为一个开源项目,也会与其他第三方平台、厂商合作适配,在swanlab前端支持外显这些平台信息。这些信息也会在采集实验元数据的时候被收集。
96+
通常,这些信息与您的训练任务没有太大关系,您可以忽略它们。
97+
98+
### 隐私保护
99+
100+
> ⚠️这是一个即将支持的功能,目前还在开发排期中。一些api可能会有所变动。
101+
102+
swanlab的信息收集功能是默认开启的,如果您不希望swanlab记录这些信息,在未来(因为还没来得及开发)您可以选择不记录这些信息,交互api类似:
103+
104+
```python
105+
import swanlab
106+
swanlab.set_private() # noqa
107+
```
108+
109+
这样swanlab的部分功能将被禁用,包括:
110+
111+
1. 实验元数据收集
112+
2. 硬件监控
113+
3. ...

docs/硬件信息采集.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# 硬件信息采集
2+
3+
本部分提供有关swanlab所记录和跟踪硬件信息、指标的相关信息以及实现的原理。
4+
5+
## 原理
6+
7+
硬件信息的采集本质上其实依赖于在实验初始化时的[实验元信息](/docs/实验元数据.md),因为这两者实际上有上下文关系:检测什么硬件、怎么检测需要通过实验元信息来确定。
8+
在进行硬件信息的检测时,同时会附带回传一系列硬件检测函数,检测当前时刻的硬件状态,这样方便撰写监控逻辑等,也更好管理。
9+
10+
换句话说,硬件信息采集强依赖于实验元信息获取,

requirements.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
swankit==0.1.1b3
2-
swanboard==0.1.6
1+
swankit==0.1.2b2
2+
swanboard==0.1.7b1
33
cos-python-sdk-v5
44
urllib3>=1.26.0
55
requests>=2.25.0
66
click
77
pyyaml
88
psutil
9+
gputil==1.4.0
910
pynvml
1011
rich

swanlab/api/upload/model.py

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,77 @@
77
@Description:
88
上传请求模型
99
"""
10+
from datetime import datetime
1011
from enum import Enum
11-
from typing import List
12+
from typing import List, Optional
13+
14+
from swankit.callback.models import ColumnClass
15+
1216
from swanlab.data.modules import MediaBuffer
13-
from datetime import datetime
1417

1518

1619
class ColumnModel:
1720
"""
1821
列信息上传模型
1922
"""
2023

21-
def __init__(self, key, column_type: str, error: dict = None):
24+
def __init__(
25+
self,
26+
key,
27+
name: Optional[str],
28+
cls: ColumnClass,
29+
typ: str,
30+
section_name: Optional[str],
31+
section_type: Optional[str],
32+
error: dict = None,
33+
):
2234
"""
23-
:param key: 列名称
24-
:param column_type: 列类型,'FLOAT', 'IMAGE', 'AUDIO', 'TEXT',必须为大写,如果传入 'DEFAULT',则会转为 'FLOAT'
25-
:param error: 错误信息,如果错误信息不为None
35+
Args:
36+
key: 键
37+
name: 键的名称
38+
cls: 键的类别
39+
typ: 键的类型
40+
section_name: 键所在的section的名称
41+
section_type: 键所在的section的类型
42+
error: 错误信息
2643
"""
2744
self.key = key
28-
self.column_type = column_type
45+
self.name = name
46+
self.cls = cls
47+
self.typ = typ
48+
self.section_name = section_name
49+
self.section_type = section_type
2950
self.error = error
3051

3152
def to_dict(self):
3253
"""
3354
序列化为Dict
3455
"""
35-
return {
36-
"key": self.key,
37-
"type": self.column_type,
38-
} if self.error is None else {
56+
d = {
57+
"class": self.cls,
58+
"type": self.typ,
3959
"key": self.key,
40-
"type": self.column_type,
41-
"error": self.error
60+
"name": self.name,
61+
"error": self.error,
62+
"sectionName": self.section_name,
63+
"sectionType": self.section_type,
4264
}
65+
if self.name is None:
66+
d.pop("name")
67+
if self.error is None:
68+
d.pop("error")
69+
if self.section_name is None:
70+
d.pop("sectionName")
71+
if self.section_type is None:
72+
d.pop("sectionType")
73+
return d
4374

4475

4576
class MetricType(Enum):
4677
"""
4778
指标类型枚举
4879
"""
80+
4981
SCALAR = "scalar"
5082
"""
5183
标量指标
@@ -64,6 +96,7 @@ class MediaModel:
6496
"""
6597
媒体指标信息上传模型
6698
"""
99+
67100
type = MetricType.MEDIA
68101

69102
def __init__(
@@ -73,7 +106,7 @@ def __init__(
73106
key_encoded: str,
74107
step: int,
75108
epoch: int,
76-
buffers: List[MediaBuffer] = None
109+
buffers: List[MediaBuffer] = None,
77110
):
78111
self.metric = metric
79112
self.step = step
@@ -99,14 +132,15 @@ def to_dict(self):
99132
**self.metric,
100133
"key": self.key,
101134
"index": self.step,
102-
"epoch": self.epoch
135+
"epoch": self.epoch,
103136
}
104137

105138

106139
class ScalarModel:
107140
"""
108141
标量指标信息上传模型
109142
"""
143+
110144
type = MetricType.SCALAR
111145

112146
def __init__(self, metric: dict, key: str, step: int, epoch: int):
@@ -123,7 +157,7 @@ def to_dict(self):
123157
**self.metric,
124158
"key": self.key,
125159
"index": self.step,
126-
"epoch": self.epoch
160+
"epoch": self.epoch,
127161
}
128162

129163

@@ -137,7 +171,7 @@ def __init__(
137171
requirements: str = None,
138172
metadata: dict = None,
139173
config: dict = None,
140-
create_time: datetime = None
174+
create_time: datetime = None,
141175
):
142176
self.requirements = requirements
143177
self.metadata = metadata

0 commit comments

Comments
 (0)