已合并
Update readme and add defualt_loader patch #117
wang-guangbin创建于 2024年8月7日
Update readme and add defualt_loader patch #117
已合并
从refs/pull/117/head合入到master
共 4 个文件变更+53-77
| @@ -12,3 +12,5 @@ reviewers: | |||
| 12 | - dilililiwhy | 12 | - dilililiwhy |
| 13 | - shaoyf | 13 | - shaoyf |
| 14 | - wang-guangbin | 14 | - wang-guangbin |
| 15 | +- liu-jiaweikf | ||
| 16 | +- zqwzju | ||
| @@ -17,9 +17,9 @@ | |||
| 17 | **前提条件** | 17 | **前提条件** |
| 18 | - 需完成CANN开发或运行环境的安装,具体操作请参考《[CANN 软件安装指南](https://www.hiascend.com/document/detail/zh/canncommercial/601/envdeployment/instg/instg_000002.html)》。 | 18 | - 需完成CANN开发或运行环境的安装,具体操作请参考《[CANN 软件安装指南](https://www.hiascend.com/document/detail/zh/canncommercial/601/envdeployment/instg/instg_000002.html)》。 |
| 19 | - 需完成PyTorch Adapter插件安装,具体请参考 https://gitee.com/ascend/pytorch 。 | 19 | - 需完成PyTorch Adapter插件安装,具体请参考 https://gitee.com/ascend/pytorch 。 |
| 20 | +- 昇腾软件栈需要安装的版本请参考[版本配套表](#版本配套表) | ||
| 20 | - Python支持版本为3.8.X,3.9.X,3.10.X,PyTorch支持版本为2.1.0, Torchvision支持版本为0.16.0。 | 21 | - Python支持版本为3.8.X,3.9.X,3.10.X,PyTorch支持版本为2.1.0, Torchvision支持版本为0.16.0。 |
| 21 | 22 | ||
| 22 | - | ||
| 23 | **安装步骤** | 23 | **安装步骤** |
| 24 | 24 | ||
| 25 | 1. 编译安装Torchvision。 | 25 | 1. 编译安装Torchvision。 |
| @@ -42,6 +42,7 @@ | |||
| 42 | ``` | 42 | ``` |
| 43 | 43 | ||
| 44 | 2. 编译安装Torchvision Adapter插件。 | 44 | 2. 编译安装Torchvision Adapter插件。 |
| 45 | + 使用最新版本,可拉取对应分支最新代码编译安装,稳定版本可以切换到对应分支的tag, 参考[版本配套表](#版本配套表)。 | ||
W | |||
| 45 | 46 | ||
| 46 | 按照以下命令进行编译安装。 | 47 | 按照以下命令进行编译安装。 |
| 47 | 48 | ||
| @@ -49,9 +50,11 @@ | |||
| 49 | # 下载Torchvision Adapter代码,进入插件根目录 | 50 | # 下载Torchvision Adapter代码,进入插件根目录 |
| 50 | git clone https://gitee.com/ascend/vision.git vision_npu | 51 | git clone https://gitee.com/ascend/vision.git vision_npu |
| 51 | cd vision_npu | 52 | cd vision_npu |
| 52 | - git checkout master | 53 | + git checkout v0.16.0-6.0.rc2 |
| 53 | # 安装依赖库 | 54 | # 安装依赖库 |
| 54 | pip3 install -r requirement.txt | 55 | pip3 install -r requirement.txt |
| 56 | + # 初始化CANN环境变量 | ||
| 57 | + source /usr/local/Ascend/ascend-toolkit/set_env.sh # Default path, change it if needed. | ||
| 55 | # 编包 | 58 | # 编包 |
| 56 | python setup.py bdist_wheel | 59 | python setup.py bdist_wheel |
| 57 | # 安装 | 60 | # 安装 |
| @@ -69,6 +72,7 @@ | |||
| 69 | # Default path, change it if needed. | 72 | # Default path, change it if needed. |
| 70 | source /usr/local/Ascend/ascend-toolkit/set_env.sh | 73 | source /usr/local/Ascend/ascend-toolkit/set_env.sh |
| 71 | ``` | 74 | ``` |
| 75 | + 注:docker中运行使用dvpp功能,需要映射`/dev/dvpp_cmdlist`设备文件 | ||
| 72 | 76 | ||
| 73 | ## NPU 适配。 | 77 | ## NPU 适配。 |
| 74 | 78 | ||
| @@ -188,72 +192,18 @@ | |||
| 188 | 192 | ||
| 189 | 1. 脚本适配。 | 193 | 1. 脚本适配。 |
| 190 | 194 | ||
| 191 | - 通过以下方式使能DVPP加速,在导入torchvision相关包后导入torchvision_npu包,在构造dataset前设置图像处理后端为npu: | 195 | + 通过以下方式使能DVPP加速,在导入torchvision相关包后导入torchvision_npu包。 |
| 192 | - ```python | 196 | +```python |
| 193 | # 使能DVPP图像处理后端 | 197 | # 使能DVPP图像处理后端 |
| 194 | ... | 198 | ... |
| 199 | + import torch | ||
| 200 | + import torch_npu | ||
| 195 | import torchvision | 201 | import torchvision |
| 196 | import torchvision_npu # 导入torchvision_npu包 | 202 | import torchvision_npu # 导入torchvision_npu包 |
| 197 | - import torchvision.datasets as datasets | 203 | + |
| 198 | - ... | ||
| 199 | torchvision.set_image_backend('npu') # 设置图像处理后端为npu,即使能DVPP加速 | 204 | torchvision.set_image_backend('npu') # 设置图像处理后端为npu,即使能DVPP加速 |
| 200 | - ... | 205 | + npu_input = torch.randint(0, 256, (4, 3, 480, 960), dtype=torch.uint8).npu() |
| 201 | - train_dataset = torchvision.datasets.ImageFolder(...) | 206 | + output = torchvision.transforms.functional.center_crop(npu_input, (100, 200)) |
| 202 | - ... | ||
| 203 | - ``` | ||
| 204 | - | ||
| 205 | - 数据预处理多进程场景下,worker进程默认运行在主进程设置的device上(如无设置默认0)。 | ||
| 206 | - 可通过set_accelerate_npu接口设置worker进程的device,例如: | ||
| 207 | - ``` python | ||
| 208 | - # 设置worker进程的device_id | ||
| 209 | - ... | ||
| 210 | - train_dataset = torchvision.datasets.ImageFolder(...) | ||
| 211 | - train_dataset.set_accelerate_npu(npu=1) # npu参数表示要设置的device_id | ||
| 212 | - ... | ||
| 213 | - ``` | ||
| 214 | - | ||
| 215 | - 部分网络脚本的ImageFolder中不包括ToTensor,DataLoader中collate_fn使用自定义的fast_collate,进行数据从PIL.Image.Imgae对象到torch.Tensor的转换。此时,使用DVPP加速需要关闭fast_collate使用默认的defualt_collate。 | ||
| 216 | - ```python | ||
| 217 | - ''' 用户脚本中自定义的collate函数 ''' | ||
| 218 | - def fast_collate(batch): | ||
| 219 | - imgs = [img[0] for img in batch] | ||
| 220 | - targets = torch.tensor([target[1] for target in batch], dtype=torch.int64) | ||
| 221 | - w = imgs[0].size[0] | ||
| 222 | - h = imgs[0].size[1] | ||
| 223 | - tensor = torch.zeros((len(imgs), 3, h, w), dtype=torch.uint8) | ||
| 224 | - for i, img in enumerate(imgs): | ||
| 225 | - nump_array = np.asarray(img, dtype=np.uint8) | ||
| 226 | - if nump_array.ndim < 3: | ||
| 227 | - nump_array = np.expand_dims(nump_array, axis=-1) | ||
| 228 | - # 如果此处没有进行nump_array从(H, W, C)到(C, H, W)的转换,那么转换会放在训练中 | ||
| 229 | - nump_array = np.rollaxis(nump_array, 2) | ||
| 230 | - tensor[i] += torch.from_numpy(nump_array) | ||
| 231 | - | ||
| 232 | - return tensor, targets | ||
| 233 | - ... | ||
| 234 | - train_loader = torch.utils.data.DataLoader( | ||
| 235 | - train_dataset, batch_size=args.batch_size, shuffle=(train_sampler is None), | ||
| 236 | - num_workers=args.workers, pin_memory=True, sampler=train_sampler, | ||
| 237 | - # collate_fn=fast_collate, drop_last=True) | ||
| 238 | - drop_last=True) # 使用collate_fn的默认defualt_collate | ||
| 239 | - ... | ||
| 240 | - if 'npu' in args.device: | ||
| 241 | - # images = images.npu(non_blocking=True).permute(0, 3, 1, 2).to(torch.float).sub(mean).div(std) | ||
| 242 | - # 如果轴转换放在训练中,使用DVPP加速时需要去掉 | ||
| 243 | - images = images.npu(non_blocking=True).to(torch.float).sub(mean).div(std) | ||
| 244 | - target = target.npu(non_blocking=True) | ||
| 245 | - ... | ||
| 246 | - ``` | ||
| 247 | - | ||
| 248 | - 如果脚本中有多个dataset,希望一些dataset使用DVPP加速,一些使用原生处理,只需要在对应dataset构造前设置相应的处理后端,如: | ||
| 249 | - ```python | ||
| 250 | - ... | ||
| 251 | - torchvision.set_image_backend('npu') # 设置dataset1的图像处理后端为npu | ||
| 252 | - dataset1 = torchvision.datasets.ImageFolder(...) | ||
| 253 | - ... | ||
| 254 | - torchvision.set_image_backend('PIL') # 设置dataset2的图像处理后端为PIL | ||
| 255 | - dataset2 = torchvision.datasets.ImageFolder(...) | ||
| 256 | - ... | ||
| 257 | ``` | 207 | ``` |
| 258 | 208 | ||
| 259 | 2. 执行单元测试脚本。 | 209 | 2. 执行单元测试脚本。 |
| @@ -270,17 +220,16 @@ | |||
| 270 | 220 | ||
| 271 | **表 2** DVPP支持功能列表 | 221 | **表 2** DVPP支持功能列表 |
| 272 | 222 | ||
| 273 | - | datasets/transforms/io | functional | 处理结果是否和pillow完全一致 | 限制 | | 223 | + | datasets/transforms/io | functional | 处理结果是否和社区接口一致 | 限制 | |
| 274 | |----------------------|------------------|--------------------|------------------------------ | | 224 | |----------------------|------------------|--------------------|------------------------------ | |
| 275 | - | default_loader | | √ | JPEG图像分辨率: 6x4~32768x32768 | | 225 | + | default_loader | | 输出为NPU tensor,一般与to_tensor搭配使用 | JPEG图像分辨率: 6x4~32768x32768 | |
| 276 | - | ToTensor | to_tensor | √ | 分辨率: 6x4~4096x8192 | | 226 | + | ToTensor | to_tensor | 支持四维tensor输入,一般与default_loader搭配使用 | 分辨率: 6x4~4096x8192 | |
| 277 | | Normalize | normalize | √ | 分辨率: 6x4~4096x8192 | | 227 | | Normalize | normalize | √ | 分辨率: 6x4~4096x8192 | |
| 278 | - | Resize | resize | 底层实现有差异,误差±1左右 | 分辨率: 6x4~32768x32768<br>输出宽超过4096时输入宽高不能小于128x16 | | ||
| 279 | | CenterCrop<br>FiveCrop<br>TenCrop | crop | √ | 分辨率: 6x4~32768x32768 | | 228 | | CenterCrop<br>FiveCrop<br>TenCrop | crop | √ | 分辨率: 6x4~32768x32768 | |
| 280 | | Pad | pad | √ | 分辨率: 6x4~32768x32768<br>填充宽度支持范围[0,2048] | | 229 | | Pad | pad | √ | 分辨率: 6x4~32768x32768<br>填充宽度支持范围[0,2048] | |
| 281 | | RandomHorizontalFlip | hflip | √ | 分辨率: 6x4~4096x8192 | | 230 | | RandomHorizontalFlip | hflip | √ | 分辨率: 6x4~4096x8192 | |
| 282 | | RandomVerticalFlip | vflip | √ | 分辨率: 6x4~4096x8192 | | 231 | | RandomVerticalFlip | vflip | √ | 分辨率: 6x4~4096x8192 | |
| 283 | - | RandomResizedCrop<br>RandomSizedCrop | resized_crop | 底层实现有差异,误差±1左右 | 分辨率: 6x4~32768x32768<br>输出宽超过4096时输入宽高不能小于128x16 | | 232 | + | RandomResizedCrop<br>RandomSizedCrop | resized_crop | BILINEAR和BICUBIC: 误差+1左右。其他插值模式无法对标 | 分辨率: 6x4~32768x32768<br>输出宽超过4096时输入宽高不能小于128x16 | |
| 284 | | ColorJitter | adjust_hue | 底层实现有差异,误差±1左右 | 分辨率: 6x4~4096x8192 | | 233 | | ColorJitter | adjust_hue | 底层实现有差异,误差±1左右 | 分辨率: 6x4~4096x8192 | |
| 285 | | ColorJitter | adjust_contrast | 底层实现有差异,factor在[0,1]时误差±1 | 分辨率: 6x4~4096x8192 | | 234 | | ColorJitter | adjust_contrast | 底层实现有差异,factor在[0,1]时误差±1 | 分辨率: 6x4~4096x8192 | |
| 286 | | ColorJitter | adjust_brightness| 底层实现有差异,误差±1左右 | 分辨率: 6x4~4096x8192 | | 235 | | ColorJitter | adjust_brightness| 底层实现有差异,误差±1左右 | 分辨率: 6x4~4096x8192 | |
| @@ -289,19 +238,12 @@ | |||
| 289 | | RandomAffine | affine | 底层实现有差异 | 分辨率: 6x4~32768x32768 | | 238 | | RandomAffine | affine | 底层实现有差异 | 分辨率: 6x4~32768x32768 | |
| 290 | | RandomPerspective | perspective | 底层实现有差异 | 分辨率: 6x4~4096x8192 | | 239 | | RandomPerspective | perspective | 底层实现有差异 | 分辨率: 6x4~4096x8192 | |
| 291 | | RandomRotation | rotate | 底层实现有差异 | 分辨率: 6x4~32768x32768 | | 240 | | RandomRotation | rotate | 底层实现有差异 | 分辨率: 6x4~32768x32768 | |
| 292 | - | Grayscale<br>RandomGrayscale | rgb_to_grayscale | √ | 分辨率: 6x4~4096x8192 | | 241 | + | Grayscale<br>RandomGrayscale | rgb_to_grayscale | float误差±1/255, uint8误差±1 | 分辨率: 6x4~4096x8192 | |
| 293 | | RandomPosterize | posterize | √ | 分辨率: 6x4~4096x8192 | | 242 | | RandomPosterize | posterize | √ | 分辨率: 6x4~4096x8192 | |
| 294 | - | RandomSolarize | solarize | √ | 分辨率: 6x4~4096x8192 | | 243 | + | RandomSolarize | solarize | float误差在±0.1,uint对标 | 分辨率: 6x4~4096x8192 | |
| 295 | | RandomInvert | invert | √ | 分辨率: 6x4~4096x8192 | | 244 | | RandomInvert | invert | √ | 分辨率: 6x4~4096x8192 | |
| 296 | | encode_jpeg | | | 分辨率: 32x32~8192x8192<br>输出宽高需要2对齐 | | 245 | | encode_jpeg | | | 分辨率: 32x32~8192x8192<br>输出宽高需要2对齐 | |
| 297 | 246 | ||
| 298 | -4. 说明。 | ||
| 299 | - | ||
| 300 | - 只有通过torchvision.datasets.ImageFolder/DatasetFolder构造的dataset才可以使能DVPP加速。 | ||
| 301 | - | ||
| 302 | - torchvision.transforms方法对外接口不变,只支持NCHW(N=1)格式的npu tensor作为入参,其他限制见表2。 | ||
| 303 | - | ||
| 304 | - 物理机场景下,一个device上最多支持64个用户进程,即单p数据预处理进程数最多设置63。 | ||
| 305 | 247 | ||
| 306 | ## 使用DVPP视频处理后端 | 248 | ## 使用DVPP视频处理后端 |
| 307 | 249 | ||
| @@ -357,6 +299,13 @@ | |||
| 357 | | roi_align | √ | | 299 | | roi_align | √ | |
| 358 | | roi_pool | √ | | 300 | | roi_pool | √ | |
| 359 | 301 | ||
| 302 | +# 版本配套表 | ||
| 303 | + | ||
| 304 | +|Torchvision Adapter分支 |Torchvision Adapter Tag | PyTorch版本 | PyTorch Extension版本 |Torchvision版本 | 驱动版本 | CANN版本| | ||
| 305 | +| -----------------------|----------------------- | ------------- | ------------------------ | ------------- | -----| ---------| | ||
| 306 | +| master | v0.16.0-6.0.rc2 | 2.1.0 | 2.1.0.post6 | 0.16.0 | Ascend HDK 24.1.RC2 | CANN 8.0.RC2| | ||
| 307 | +| v0.12.0-dev | v0.12.0-6.0.rc2 | 1.11.0 | 1.11.0.post14 | 0.12.0 | Ascend HDK 24.1.RC2 | CANN 8.0.RC2| | ||
| 308 | + | ||
| 360 | **Torchvision Adapter适配NPU的方案见[适配指导](docs/适配指导.md)。** | 309 | **Torchvision Adapter适配NPU的方案见[适配指导](docs/适配指导.md)。** |
| 361 | 310 | ||
| 362 | # 安全声明 | 311 | # 安全声明 |
| @@ -0,0 +1,24 @@ | |||
| 1 | +import torch | ||
| 2 | +import torch_npu | ||
| 3 | +from torch_npu.testing.testcase import TestCase, run_tests | ||
| 4 | +import torchvision | ||
| 5 | +import torchvision_npu | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +class TestDefaultLoader(TestCase): | ||
| 9 | + | ||
| 10 | + def test_default_loader(self): | ||
| 11 | + path = "../Data/dog/dog.0001.jpg" | ||
| 12 | + torchvision.set_image_backend('PIL') | ||
| 13 | + img_output = torchvision.datasets.folder.default_loader(path) | ||
| 14 | + cpu_output = torchvision.transforms.functional.to_tensor(img_output) | ||
| 15 | + | ||
| 16 | + torchvision.set_image_backend('npu') | ||
| 17 | + npu_output = torchvision.datasets.folder.default_loader(path) | ||
| 18 | + npu_output = torchvision.transforms.functional.to_tensor(npu_output).squeeze(0) | ||
| 19 | + | ||
| 20 | + self.assertEqual(cpu_output, npu_output) | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +if __name__ == '__main__': | ||
| 24 | + run_tests() | ||
| @@ -40,6 +40,7 @@ def add_datasets_folder(): | |||
| 40 | torchvision.__name__ = 'torchvision_npu' | 40 | torchvision.__name__ = 'torchvision_npu' |
| 41 | torchvision.datasets.DatasetFolder = DatasetFolder | 41 | torchvision.datasets.DatasetFolder = DatasetFolder |
| 42 | torchvision.datasets.ImageFolder = ImageFolder | 42 | torchvision.datasets.ImageFolder = ImageFolder |
| 43 | + torchvision.datasets.folder.default_loader = default_loader | ||
| 43 | 44 | ||
| 44 | 45 | ||
| 45 | def _assert_image_3d(img: torch.Tensor): | 46 | def _assert_image_3d(img: torch.Tensor): |
已更改,配套表已更新tag对应的分支