Petrel OSS SDK 2.0
注意:该版本SDK需要python3.6环境
若之前安装过旧版本,请先运行
$ pip uninstall pycephs3client
$ rm -rf ~/.local/lib/python3.6/site-packages/petrel_client
建议在安装之前先升级 pip
source /mnt/lustre/share/platform/env/<pat... or pt...> # 请根据实际情况确定是否需要 source
python3 -m pip install --upgrade pip # 请根据实际情况确定是否需要 `sudo` 或添加 `--user` 参数
训练集群环境上安装
$ source /mnt/lustre/share/platform/env/<pat... or pt...>
$ python setup.py sdist
$ pip install --user dist/*
通过修改 PYTHONPATH 安装
$ source /mnt/lustre/share/platform/env/<pat... or pt...>
# 安装SDK依赖
$ python setup.py egg_info
$ pip install -r *.egg-info/requires.txt
# 将SDK编译到 ./build 目录
$ python setup.py build
# 修改 PYTHONPATH 环境变量
$ export PYTHONPATH=<path_to_sdk>/build/lib:$PYTHONPATH
venv环境上安装
$ python3 -m venv your_venv_name # 若已创建venv环境则无需执行
$ source your_venv_name/bin/active
$ python setup.py sdist
$ pip install dist/*
系统环境上安装
$ python3 setup.py sdist
$ python3 -m pip install dist/* # 请根据实际情况确定是否需要 `sudo` 或添加 `--user` 参数
使用
SDK 提供 get
和 put
接口,使用方式为
data = client.get(url) # 默认情况由配置文件决定是否使用 MC
data = client.get(url, no_cache=True) # 本次 get 直接从 ceph 读取
data = client.get(url, update_cache=True) # 本次 get 直接从 ceph 读取,并将数据缓存至 MC
client.put(url, data) # 默认 put 不会更新 MC
client.put(url, data, update_cache=True) # 本次 put 将数据存入 ceph 之后并更新 MC
注意:
若配置文件中没有启用 MC
,则 no_cache
和 update_cache
参数将被忽略
以下为使用 SDK 读取图片、进行图片处理后并保存图片的简单例子
import cv2
import numpy as np
from os.path import splitext
from petrel_client.client import Client
conf_path = '~/petreloss.conf'
client = Client(conf_path) # 若不指定 conf_path ,则从 '~/petreloss.conf' 读取配置文件
img_url = 's3://bucket1/image.jpeg'
img_gray_url = 's3://bucket1/image_gray.jpeg'
img_ext = splitext(img_gray_url)[-1]
# 图片读取
img_bytes = client.get(img_url)
assert(img_bytes is not None)
img_mem_view = memoryview(img_bytes)
img_array = np.frombuffer(img_mem_view, np.uint8)
img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
# 图片处理
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 图片存储
success, img_gray_array = cv2.imencode(img_ext, img_gray)
assert(success)
img_gray_bytes = img_gray_array.tostring()
client.put(img_gray_url, img_gray_bytes)
配置文件请参考 petreloss.conf
请注意:配置文件中 `key = value` 的 key 前面不能有空格,否则该行视为上一行配置项 value 的一部分
使用样例请参考 multi_cluster_test.py
Tensor
和 Json
数据保存与读取
使用样例 tensor_json_test.py
Pillow Image
数据保存与读取
使用样例 pillow_image_test.py
数据过大无法上传,则需要分片上传
使用样例 multipart_test.py
创建 Bucket
client.create_bucket('s3://mybucket')
顺序的读取某个前缀的数据
cluster = 'cluster1'
files = client.get_file_iterator('cluster1:s3://lili1.test2/test3')
for p, k in files
key = '{0}:s3://{1}'.format(cluster, p)
data = client.get(key)
使用 anonymous 账户访问数据
若在配置文件中不设置 access_key
和 secret_key
,将以 anonymous
账户访问数据。
McKeySizeExceed 错误
默认情况下,MC
所支持 key
的最大长度为250个字节。如果路径过长,将会出现 McKeySizeExceed
错误。
此时需要用户定义 key
的转换规则来避免该错误。
注意:
中文字符对应多个字节。
例如:
def trim_key(key):
if isinstance(key, str):
key = key.encode('utf-8')
else:
assert isinstance(key, bytes)
return key[-249:]
client = Client('~/petreloss.conf', mc_key_cb=trim_key)
此外,可使用内置函数 md5
、sha256
等,例如:
client = Client('~/petreloss.conf', mc_key_cb='sha256')
或在配置文件中指定:
[mc]
mc_key_cb = sha512
请注意
- 用户需要保证转换规则结果的唯一性,内置转换函数也有可能发生哈希碰撞。
- 如果
key
为str
类型且其中出现中文字符,请务必用encode('utf-8')
对其进行编码。
使用伪客户端
在对应客户端添加如下配置:
fake = True
配置文件请参考 fake_client.conf
使用样例请参考 fake_client_test.py
强制更新MC
使用 get_and_update
接口或在 get
中传入 update_cache=True
参数将直接从存储系统读取数据并更新MC。
IO 统计信息
IO 统计信息可通过以下三种方式修改其log
输出频度:
- 由环境变量
count_disp
设置 - 由配置文件
count_disp
设置 (若已设置环境变量,则该方式无效) - 调用
client.set_count_disp(count_disp)
(该方式将覆盖上述两种方式),但限于parrots
和pytorch
的运行机制,在某些使用场景下可能无法有效修改。
若 count_disp
为 0
,则将关闭 IO 统计信息打印。
若需要在 console
中打印 IO 统计信息,则需要设置 console_log_level
为 INFO
或更低级别,且 count_disp
需大于 0
。
DataLoader
SDK
提供的 DataLoader
额外支持如下参数:
prefetch_factor
,默认2。每个worker
预读batch
数目。persistent_workers
,默认False
。如果为True
,则每轮epoch
迭代完毕后worker
进程将不会关闭,下轮epoch
将复用该worker
进程。
用例:
from petrel_client.utils.data import DataLoader
dataloader = DataLoader(dataset=xxx, ..., prefetch_factor=4, persistent_workers=True)
SSL 验证
使用 https
协议时默认不会对 SSL
进行验证。若需要开启验证,请在配置文件中进行如下设置
verify_ssl = True
Presigned URL,生成签名链接
presigned_url = client.generate_presigned_url(url, client_method ='get_object', expires_in=3600)
client_method
取值为 get_object
(默认值) 或 put_object
expires_in
单位为秒,默认值为 3600
Presigned POST,生成签名 POST
presigned_post = client.generate_presigned_post(url, fields=None, conditions=None, expires_in=3600)
参数及返回值详见 generate_presigned_post,其中参数 bucket 和 key 从 url 中提取。
Range 读取
range 的形式有如下几种
- '
first_byte_pos
-':读取first_byte_pos
及后续的所有数据 - '
first_byte_pos
-last_byte_pos
':读取first_byte_pos
到last_byte_pos
(包含)的数据 - '-
suffix_length
':读取最后suffix_length
字节的数据
具体详见 HTTP 中 Range 的定义:https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 ,但ceph目前不支持多个 Range 读取。
# 假设数据长度为 10000 字节
# 读取第一段 500 字节数据
data1 = client.get(url, range='0-499')
# 读取第二段 500 字节数据
data2 = client.get(url, range='500-999')
# 读取最后 500 字节数据
data_last = client.get(url, range='-500')
# 或
data_last = client.get(url, range='9500-')
以流的形式读取数据
stream = client.get(url, enable_stream=True)
返回的 stream
为 StreamingBody
,使用方法详见
https://botocore.amazonaws.com/v1/documentation/api/latest/reference/response.html
判断对象是否存在
exists = client.contains(url)
查询对象大小
size = client.size(url)
若对象不存在,产生 NoSuchKeyError
异常
删除对象
client.delete(url)
列出当前路径包含的对象或目录
contents = client.list(url)
for content in contents:
if content.endswith('/'):
print('directory:', content)
else:
print('object:', content)
判断目录是否存在
client.isdir(url)
注意:Ceph
中没有目录的概念,本函数返回True
时代表存在以该url
作为前缀的对象,其他情况返回False
。
使用 /mnt/cache
目录下的 Python
环境
相对于 /mnt/lustre
目录,在 /mnt/cache
目录执行 Python
有一定的性能提升。
使用方式如下:
source
/mnt/cache
目录下的Python
环境
### 例如 pt1.3v1
source /mnt/cache/share/platform/env/pt1.3v1
### 或 s0.3.3
source /mnt/cache/share/spring/s0.3.3
- 检查
Python
路径是否正确
which python
### 结果应为 /mnt/cache/...
- 设定
PYTHONUSERBASE
环境变量
export PYTHONUSERBASE=/mnt/cache/<username>/.local
- 重新安装相关依赖库(仅需首次使用时执行)
python -m pip install --user <packages>