MXNet结合kubeflow进行分布式训练

GPU集群配置MXNet+CUDA

为方便控制集群,写了脚本cmd2all.sh

#!/bin/bash
if [ $# -lt 3 ]; thenecho "usage: $0 [type cmds hosts]"echo "for example: ./cmd2all.sh \"cmds\" \"touch t1.txt\" \"gpu1 gpu2\""echo "for example: ./cmd2all.sh \"path\" \"/home/gbxu/CUDA/" \"gpu1 gpu2\""exit -1;
fi
type=$1 # "cmds"
cmds_or_path=$2 # "touch test.txt"
#hosts=$3
hosts=(gpu10 gpu11 gpu12 gpu13 gpu14 gpu15 gpu16 gpu17 gpu18)
if [$type == "cmds"]
thenfor host in ${hosts[@]}dossh $host nohup $cmds_or_path  &done
fiif [$type == "path"]
thenfor host in ${hosts[@]}donohup scp -r $cmds_or_path $host:~/ &done
fi

使用virtualenv

如果是python3的环境,需要virtualenv -p /usr/bin/python3 mxnetGPU
使用virtualenv,创建新的virtualenv,并修改.bashrc,使得在每次进入终端时activate虚拟环境(方便后期分布式运行)

hosts="gpu10 gpu11 gpu12 gpu13 gpu14 gpu15 gpu16 gpu17 gpu18 "
./cmd2all.sh "cmds" "sudo yum -y install epel-release && sudo yum -y install python-pip && sudo pip install virtualenv && virtualenv mxnetGPU" $hosts
./cmd2all.sh "cmds"  "echo \"## gbxu MXnet-GPU\" >> .bashrc" $hosts
./cmd2all.sh "cmds"  "echo \"source mxnetGPU/bin/activate\" >> .bashrc" $hosts

尝试在gpu10安装

Install NVIDIA Driver

本身已有驱动则该操作不必要。

lspci | grep -i nvidia #查看设备
modinfo nvidia #查看驱动
sudo yum -y remove nvidia-*
sudo sh  NVIDIA-Linux-x86_64-390.25.run #安装驱动

Install CUDA:

see documents:

  • offline安装,online版本可能出现依赖缺失。
  • 所有版本
    CUDA是NVIDIA推出的用于自家GPU的并行计算框架,只有当要解决的计算问题是可以大量并行计算的时候才能发挥CUDA的作用。
    下载: 见offline安装
#copy installer && run# 若安装错误需要先卸载
sudo yum -y remove "cuda-*"
sudo rm -rf /usr/local/cuda*
sudo rpm -i cuda-repo-rhel7-9-2-local-9.2.148-1.x86_64.rpm
sudo yum clean all
sudo yum -y install cuda

gpu10利用yum local的安装出现问题,后来下载cuda_9.2.148_396.37_linux.run
sudo sh cuda_9.2.148_396.37_linux.run安装
并且在安装(or not, just try)时同意nvidia驱动,并且一路yes和default。
or, add /usr/local/cuda-9.2/lib64 to /etc/ld.so.conf and run ldconfig as root

添加CUDA环境变量

# export LD_LIBRARY_PATH=/usr/local/cuda/lib64/:$LD_LIBRARY_PATH
echo -e "export LD_LIBRARY_PATH=/usr/local/cuda/lib64/:\$LD_LIBRARY_PATH" >> .bashrc 
# export PATH=$PATH:/usr/local/cuda/bin
echo -e "export PATH=\$PATH:/usr/local/cuda/bin" >> .bashrc

测试CUDA

nvcc -V
nvidia-smi
cd /home/gbxu/NVIDIA_CUDA-9.2_Samples/1_Utilities/deviceQuery
make
./deviceQuery # 结果pass则安装成功

Install cuDNN:

see documents
cuDNN(CUDA Deep Neural Network library):是NVIDIA打造的针对深度神经网络的加速库,是一个用于深层神经网络的GPU加速库。如果你要用GPU训练模型,cuDNN不是必须的,但是一般会采用这个加速库。

tar -xzvf cudnn-9.2-linux-x64-v7.1.tgz
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn.h

安装Prerequisites

see documents

sudo yum -y install build-essential git lapack-devel openblas-devel opencv-devel atlas-devel

complie MXNet

see:documents

git clone --recursive https://github.com/apache/incubator-mxnet.git
cd incubator-mxnet
make clean_all
make -j $(nproc) USE_OPENCV=1 USE_BLAS=openblas USE_CUDA=1 USE_CUDA_PATH=/usr/local/cuda USE_CUDNN=1 USE_DIST_KVSTORE=1  USE_PROFILER=1 

install MXNet in python

cd python
pip uninstall -y mxnet
pip install -e .

test MXNet in python

python
>>> import mxnet as mx                                                                                                                                                      
>>> a = mx.nd.zeros((2,3), mx.gpu())

install python lib

请根据最后运行MXNet任务时查缺补漏

pip install numpy requests 

预设编译参数

cd到源代码主目录,在makefile文件中预设编译参数,

# vim incubator-mxnet/Makefile
cmpl:make -j $(nproc) USE_OPENCV=1 USE_BLAS=openblas USE_DIST_KVSTORE=1cmplgpu:make -j $(nproc) USE_OPENCV=1 USE_BLAS=openblas USE_DIST_KVSTORE=1 USE_CUDA=1 USE_CUDA_PATH=/usr/local/cuda USE_CUDNN=1 

之后使用make指令编译更为便捷。

make cmplgpu

批量安装环境

在gpu11-gpu18批量安装环境

先用1.sh将数据传到nodes,

  • 1.sh
hosts=(gpu11 gpu12 gpu13 gpu14 gpu15 gpu16 gpu17 gpu18)
for host in ${hosts[@]}
doecho run 1.sh at $hostscp -r process_data gbxu@$host:~/
done

再用2.sh在各nodes运行scripts_in_nodes.sh脚本即可。

  • 2.sh
hosts=(gpu12 gpu13 gpu14 gpu15 gpu16 gpu17 gpu18)
for host in ${hosts[@]}
doecho run 2.sh at $hostscp process_data/scripts_in_nodes.sh gbxu@$host:~/process_data/ssh gbxu@$host "cd process_data && nohup ./scripts_in_nodes.sh &"
done
  • scripts_in_nodes.sh
sudo yum -y remove "cuda-*" 
sudo rpm -i cuda-repo-rhel7-9-2-local-9.2.148-1.x86_64.rpm
sudo yum clean all
sudo yum -y install cuda
echo -e "export LD_LIBRARY_PATH=/usr/local/cuda/lib64/:\$LD_LIBRARY_PATH" >> ~/.bashrc
echo -e "export PATH=\$PATH:/usr/local/cuda/bin" >> ~/.bashrctar -xzvf cudnn-9.2-linux-x64-v7.1.tgz
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn.hsudo yum -y install build-essential git lapack-devel openblas-devel opencv-devel atlas-develpip install numpy requests # 请根据最后运行MXNet任务时查缺补漏

编译、安装MXNet

之后只需在一台host上编译mxnet即可,余下用MXNet的同步机制即可。
在gpu10上启动训练

  • 需要加库文件放到同步的文件夹下:
cd incubator-mxnet/example/image-classification
echo -e "gpu11\ngpu12\ngpu13\ngpu14\ngpu15\ngpu16\ngpu17\ngpu18\n" > hosts
rm -rf mxnet
cp -r ../../python/mxnet .
cp -r ../../lib/libmxnet.so mxnet
  • 然后执行命令,该命令会同步文件夹cluster上启动8个worker,1个server
# export DMLC_INTERFACE='ib0'; # ib尚未配置好
python ../../tools/launch.py -n 8 -s 1 --launcher ssh -H hosts --sync-dst-dir /home/gbxu/image-classification_test/  python train_mnist.py --network lenet --kv-store dist_sync --num-epochs 1 --gpus 0

ENJOY

  • multiple machines each containing multiple GPUs 的训练见docs
  • 其中 dist_sync_device 替代 dist_sync。因为cluster为多GPU,见docs
  • mxnet-make-install-test.sh
cd incubator-mxnet
make clean_all
make -j $(nproc) USE_OPENCV=1 USE_BLAS=openblas USE_CUDA=1 USE_CUDA_PATH=/usr/local/cuda USE_CUDNN=1 USE_DIST_KVSTORE=1  USE_PROFILER=1 
cd python
pip uninstall -y  mxnet
pip install -e .
cd ../example/image-classification
echo -e "gpu11\ngpu12\ngpu13\ngpu14\ngpu15\ngpu16\ngpu17\n" > hosts
rm -rf mxnet # example/image-classification下的
cp -r ../../python/mxnet .
cp -r ../../lib/libmxnet.so mxnet
export DMLC_INTERFACE='ib0';
python ../../tools/launch.py -n 8 -s 1 --launcher ssh -H hosts --sync-dst-dir /home/gbxu/image-classification_test/  python train_mnist.py --network lenet --kv-store dist_sync --num-epochs 1 --gpus 0

 

 

MXNet 以数据并行的方式进行单机多卡训练

 

MXNet 支持在多 CPU 和 GPU 上进行训练。其中,这些 CPU 和 GPU 可以分布在不同的服务器上。

 

一台 GPU 机器上的每块 GPU 都有自己的编号(编号从 0 开始计数)。如果想使用某一块特定的 GPU 卡,即可以在代码中直接指定 context(ctx); 也可以在命令行中传递参数–gpus。

 

例如: 如果想在 python 中使用 GPU 0 和 GPU 2,可以使用下面的代码创建网络模型。

 

 

如果多个 GPU 的计算能力不同,那么可以根据它们的计算性能来划分工作负载。比如,如果 GPU 0 是 GPU 2 性能的 3 倍,那么可以提供一个额外的负载选项 work_load_list=[3, 1]。

 

如果所有其它超参都相同,在多个 GPU 上训练结果应该和单 GPU 上的训练结果相同。但在实际应用中,由于随机存取(随机顺序或其它 augmentations),使用不同的种子初始化权重和 CuDNN,结果可能不同。

 

我们可以控制梯度聚合和模型更新(如执行,训练过程)的位置,通过创建不同的 KVStore(数据通信模块)。即可以使用 mx.kvstore.create(type)来创建一个实例,也可以使用程序的参数–kv-store type 来实现功能。

 

两种常用功能

 

  • local: 所有的梯度都拷贝到CPU内存完成聚合,同时在CPU内存上完成权值的更新并拷贝回每个GPUworker。这种方式主要在于CPU与GPU,主要的性能负载在于CPU拷贝的负载。

  • device: 梯度聚合和权值更新都在GPU上完成。GPU之间的如果支持Peer to Peer通信(PCIe or NVLink),将避免CPU拷贝的负载,可以大大减轻CPU的负担,仅受限于通信带宽。PCIe 与NVLink通信带宽不同,NVLink具备告诉的Peer to Peer通信带宽。

 

注意: 如果有大量的 GPU(比如: >=4),建议使用 device 能获取更好的性能。

 

MXNet 以数据并行的方式进行多机多卡训练

 

在介绍 MXNet 分布式训练之前,先介绍几个关键性的概念方便理解 MXNet 的分布式训练:

 

三种进程类型

 

  • Worker: worker进程会对每一批次(batch_size)的数据样本进行训练。对批数据进行处理之前,workers会从servers服务器pull权重。对批处理数据处理完毕之后workers会聚合梯度数据发送给servers。(如果训练模型的工作负载比较高,建议最好不要把worker和server运行在相同的机器上)。

  • Server: 可以运行多个server服务进程,用于存储模型参数并与worker进行通讯。

  • Scheduler: 一个调度器,在集群中负责调度的角色。主要包含: 等待各个node节点数据的上报数据并让各个node节点知道彼此的存在并互相通讯。

 

进程之间的关系如下图所示:

 

 

工作流程:

 

1.worker, server 向 scheduler 注册,获取相关的信息。

 

2.worker 从 server 端 pull 参数 w。

 

3.worker 基于参数 w 和数据计算梯度,然后 push 梯度到 server。

 

4.server 更新参数 w。

 

5.反复执行 2-4 过程。

 

KVStore

 

KVStore 是 MXNet 提供的一个分布式 key-value 存储,用来进行数据交换。KVStore 本质的实现是基于参数服务器。

 

  • 通过引擎来管理数据一致性,这使得参数服务器的实现变得简单,同时使得KVStore的运算可以无缝的与其他部分结合在一起。

  • 使用两层的通讯结构,原理如下图所示。第一层的服务器管理单机内部的多个设备之前的通讯。第二层服务器则管理机器之间通过网络的通讯。第一层的服务器在与第二层通讯前可能合并设备之间的数据来降低网络带宽消费。同时考虑到机器内和外通讯带宽和延时的不同性,可以对其使用不同的一致性模型。例如第一层用强的一致性模型,而第二层则使用弱的一致性模型来减少同步开销。

 

 

通过调用 mxnet.kvstore.create()函数并传递 dist 关键字参数来开启分布式训练的 KVStore 模式:

 

 

kv = mxnet.kvstore.create(‘dist_sync’)

 

复制代码

 

分布式训练模式

 

当 KVStore 被创建并且包含 dist 关键参数就会开启分布式训练模式。通过使用不同类型的 KVStore,可以启用不同的分布式培训模式。具体如下:

 

  • dist_sync: 已同步的方式进行分布式训练,在处理每批次(batch)的数据时,所有的workers需要使用相同的模型参数集合。这意味着servers参数服务需要接收来自所有workers模型参数之后,才能进行下一个批次数据的处理。因此在使用这种分布式训练方式时,server参数服务需要等到所有的worker处理完毕之后,并且如果其中的某一个worker异常,会导致整个训练的过程halts。

  • dist_async: 已异步的方式进行分布式训练,server参数服务只要收到worker的计算梯度就会立即更新存储。这意味着哪个worker处理完当前的批次数据,就可以继续下一批次数据的处理。因此该种方式的分布式训练方式比dist_sync要快,但是需要花费更多的epochs去收敛。

  • dist_sync_device: 该分布式训练模式与dist_sync训练模式相同,只是dist_sync_device模式会在多GPUs上进行梯度聚合和更新权重,而dist_sync是在CPU上进行这些操作。这种模式比dist_sync要快,因为GPU和CPU之前的通信,但是会占用更多的GPU显存。

  • dist_async_device: 该模式和dist_sync_device类似,但是是已异步的方式进行的。

 

开启分布式训练

 

MXNet 为了用户方便的进行分布式训练提供了一个 tools/launch.py 脚本。并且支持对多种类型的集群资源进行管理,如: ssh,mpirun,yarn,sge。

 

 

如上图所示,将代码 clone 到本地后,进入 gluon 目录,使用 image_classification.py 和 CIFAR10 数据集来对 VGG11 模型进行分布式训练。

 

虽然 MXNet 实现了多机多卡的分布式训练,但是在资源隔离,资源调度,资源限制以及大规模训练时数据共享都是不能满足需求的,所以接下来介绍下 MXNet 基于 Kubeflow 的大规模分布式训练。

 

MXNet 结合 kubeflow 进行分布式训练

 

在将 MXNet 结合 kubeflow 进行分布式训练之前,首先需要安装 kubeflow 环境之前已经介绍了,这里就不在详细说明了。当 kubeflow 基础环境部署完成之后,需要针对 MXNet 安装 mxnet-operator。

 

安装 mxnet-operator

 

 

安装完成后,执行以下命令,检验 mxnet 是否安装成功:

 

 

kubectl get crd

 

复制代码

 

输出如下内容代表 mxnet-operator 安装成功:

 

 

基于 kubeflow 测试 MXNet 分布式训练

 

1 准备测试的训练镜像

 

示例代码: https://github.com/deepinsight/insightface

 

Dockerfile 文件内容:

 

 

2 创建分布式网络文件系统数据卷(cephfs)

 

 

由于我们是基于 kubernetes 的 pv 和 pvc 的方式使用数据卷,所有集群中需要事先安装好 storage-class install,这样当用户创建 pvc 时,会通过 storage-class 自动的创建 pv。

 

当创建好 pv 之后,用户可以将该数据卷 mount 到自己的开发机上,并将需要训练的数据集移到该数据卷。用于之后创建训练 worker pod 的时候,挂载到 worker 容器中,供训练模型使用。

 

3 创建 mxnet 分布式训练任务

 

 

4 创建训练任务

 

 

kubectl create -f insightface-train.yaml

 

复制代码

 

5 查看任务运行情况

 

 

 

6 查看训练日志的信息

 

登录到具体的 node 计算节点通过 docker logs 命令查看训练的日志:

 

 

docker logs -f fc3d73161b27

 

复制代码

 

更多资讯或疑问内容添加小编微信, 回复 “Python” ,领取更多资料哦

    

总结

 

虽然已经完成了 mxnet 结合 kubeflow 实现大规模的分布式训练,但是除了功能上的基本跑通,还存在很多因素影响分布式训练的性能,如: GPU 服务器的网络带宽,普通的我们使用的以太网因为通信延迟的原因,会大大影响多机扩展性。InfiniBand(IB)网络和 RoCE 网络因为支持 RDMA,大大降低了通信延迟,相比之下,20G 的以太网格延迟会大大提升。当然,对于现有的普通以太网络,也可以通过别的方法优化通信带宽的减少,比方说梯度压缩。通过梯度压缩,减少通信带宽消耗的同时,保证收敛速度和精度不会有明显下降。MXNet 官方提供了梯度压缩算法,按照官方数据,最佳的时候可以达到两倍的训练速度提升,同时收敛速度和精度的下降不会超过百分之一。还有如果使用分布式网络文件系统进行数据集的存储,如果解决吞吐量和网络延迟的问题。以及本地磁盘是否是 SSD,还是在训练时是否需要对大文件的数据集进行 record.io 文件格式的处理及训练前数据集的切分等等问题,都需要更进一步的处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Opencv的水位识别,液面识别、高度识别

Update 代码已经上传到github上了,可以点这里 Cutting 一直说这要整理一下Computer Vision课程的大作业,拖了好久。这两天忙着写一个订单处理的第三方库,陷入了僵局,所以换个口味,把大作业整理一下。 Requirement W…

Openshift3.9部署手册

说明:本文主要介绍通过Ansible来部署Openshift 3.9 一、准备 系统准备 节点类型说明Masters 物理主机或者虚拟机 系统:Fedora 21, CentOS 7.3, 7.4或者7.5 最少4vCPU 最少16GB内存 /var/最少40GB空间 /usr/local/bin最少1GB空间 容器临时目录最少1GB空…

Solr入门——安装

为什么80%的码农都做不了架构师?>>> Solr网址http://lucene.apache.org/solr/ OSC地址:http://www.oschina.net/p/solr 下载地址:http://www.apache.org/dyn/closer.cgi/lucene/solr/4.3.1 解压 1、拷贝 solr-4.3.1/dist/…

java调用小冰,Java利用微软小冰API测颜值

【需求背景】七月入职,做了一个交友mini项目,有涉及一个给人脸颜值评分的需求。经过网上搜索,发现微软小冰可以很好解决这个需求。【说明】根据mini项目,用Spring-boot框架实现了一个demo,在html页面,上传个…

svn完整搭建

安装软件 # yum install httpd mod_dav_svn subversion mod_ssl 查看是否安装成功#svn --version 如果出现版本号如则说明svn安装成功查看httpd配置文件/etc/httpd/conf/httpd.conf如果找到这说明apache模块安装正确配置1.创建版本库# mkdir -pv /svn/date --创建主目录# svn…

Kubernetes 部署 Ingress 控制器 Traefik v1.7.4

标签: kubernetes ingress traefik nginx haproxy kong 介绍TraefikIngress 对象 上节课我们学习了在Kubernetes集群内部使用kube-dns实现服务发现的功能,那么我们部署在Kubernetes集群中的应用如何暴露给外部的用户使用呢?我们知道前面我们…

php iis redis,iis windows phpstudy安装redis扩展

说明,我的服务器是2008 64位 php5.4.33首先下载符合条件的redis扩展,是否符合条件可以参考https://pecl.php.net/package/redis,进入之后,点击"DLL"可以看到红圈里面的就是适合iis的non thread safe就是非安全线程下面那个thread safe适合apache下面两个就是下载所需…

几种常见SQL分页方式效率比较

转载地址:http://www.cnblogs.com/iamowen/archive/2011/11/03/2235068.html 分页很重要,面试会遇到。不妨再回顾总结一下。 1.创建测试环境,(插入100万条数据大概耗时5分钟)。 create database DBTestuse DBTest--创建测试表create table…

BinderHub 使用简介

使用 Binder 將公開的 GitHub Repository 轉換為可互動、可執行程式碼並能在瀏覽器上一鍵啟動的 JupyterHub 伺服器,讓我們可以快速地建造出方便分享的教學環境。 Python 3.6 JupyterLabPython 3.7 Jupyter NotebookR 3.6 JupyterHubR 3.6 RStudio 使用 Binder 與 …

Sql自动配置器原理及其说明

简介:Sa设置辅助器设计的初衷是为了抛开繁琐与重复的配置,这种繁琐到了一定程度回使人厌烦,重复到了一种程度让人觉得无趣,为了解决这种厌烦与无趣,她就出现与产生了。底下的原理适用于任何SQL Server版本与运行平台。…

Oracle 日常巡检——数据库基本情况检查

对于线上的业务,Oracle 的 数据库 运行的稳定性和安全性是用户关心的一个至关重要的问题,除了通过监控平台对数据库进行监控以外,还需要定期对数据库进行“体检”,数据库巡检是保障数据库稳定运行的必不可少的辅助手段。 本文将简…

路由器ospf动态路由配置

技术原理:Ospd开放式最短路径优先协议。是目前网络中应用最广泛的路由协议之一。属于内部网络路由协议。能够适应各种规模的网络环境,是典型的链路状态协议。Ospf路由协议通过向全网扩散本设备的链路状态信息,使网络中每台设备最终同步一个具…

Kubernetes 持久化存储 Cephfs

熟悉kubernetes volume的同学应该了解,kubernetes 对volume的提供支持“静态PV”和“动态PV”两种方式。 静态PV:集群管理员创建一些PV,之后便可用于PVC消费。 动态PV:相比静态PV而言,动态PV无需管理员手动创建PV&…

RDIFramework.NET — 系列目录 — 基于.NET的快速信息化系统开发框架

RDIFramework.NET — 基于.NET的快速信息化系统开发框架 — 系列目录RDIFramework.NET,基于.NET的快速信息化系统开发、整合框架,给用户和开发者最佳的.Net框架部署方案。框架简单介绍RDIFramework.NET,基于.NET的快速信息化系统开发、整合框…

Visual Studio项目版本转换器(c#项目版本转换器 v1.0)

Visual Studio项目版本转换器(c#项目版本转换器 v1.0) 使用截图: 下载地址:http://files.cnblogs.com/stone_w/VsConvert.zip vs转换中文通用版,目前版本只支持c#程序。 功能说明: 1.智能判断当前待转换引…

基于 Kubernetes 构建企业 Jenkins 持续集成平台

1、部署Jenkins 新建kube-ops 命名空间 $ kubectl create namespace kube-ops 新建Deployment文件(jenkins2.yaml) ---apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: jenkins2 namespace: kube-opsspec: template: metadata: labels: …

TC 配置插件

转载:http://hi.baidu.com/accplaystation/item/07534686f39dc329100ef310 1、插件下载地址:http://www.topcoder.com/tc?moduleStatic&d1applet&d2plugins 一般用下面三个插件:CodeProcessor(2.0)&#xff0…

WebClient 访问间歇性返回403解决方案

说明:前段时间做的一个项目莫名的返回403的错误,这种情况也多大是程序员最不喜欢的了,没办法先来分析一下错误信息。之前的代码如下: WebClient webclient new WebClient();string u9Str webclient.DownloadString("http:/…

bootstrap select2 php,JS组件Bootstrap Select2使用方法详解

在介绍select组件的时候,之前分享过一篇JS组件中bootstrap multiselect两大组件较量的文章,这两个组件的功能确实很强大,本文分享下select组件的一些用法和特性。一些通用的单选、多选、分组等功能这里就不多做介绍了,multiselect…

文件删除小助手

亲,还在为删除多个文件而发愁吗?还在为删除不同目录下的N多文件而发愁吗?那你就下载这个吧。 功能以及优点: 1.支持删除某一类文件。 2.支持某一路径下所有文件的检索删除。 3.支持复杂文件名称匹配。 4.免安装,绿色中…