基于Docker的深度学习环境NVIDIA和CUDA部署以及WSL和linux镜像问题
基于Docker的深度学习环境部署
- 1. 什么是Docker?
- 2. 深度学习环境的基本要求
- 3. Docker的基本操作
- 3.1 在Windows上安装Docker
- 3.2 在Ubuntu上安装Docker
- 3.3 拉取一个pytorch的镜像
- 3.4 部署自己的项目
- 3.5 导出配置好项目的新镜像
- 4. 分享新镜像
- 4.1 将镜像导出为tar分享给他人
- 4.2 或者将镜像推送到云仓库
- 5. 使用新镜像
- 6. 跨平台造成nvidia-smi不可用的问题
- 6.1 确认是该问题
- 6.2 win2linux问题如何解决?
- 6.2.1 手动创建软链接
- 6.2.2 使用Dockfile自动完成
- 6.3 linux2win问题如何解决?
- 6.3.1 在WSL使用时手动删除软链接
- 6.3.2 使用Dockerfile自动完成
- 6.3.3 不使用--gpus all的容器打包(针对镜像发布者)
- 7. 总结
- 8. 常见问题debug
- Reference
1. 什么是Docker?
docker的介绍网上有很多,对于深度学习的认来讲,docker的好处就是直接把环境分享给他人,他人不需要再配置环境了。
比如我有一个目标检测的项目,我想分享给朋友,那么他首先需要在自己的电脑上配置好显卡驱动、CUDA、CuDNN,在拿到我的项目后,还需要安装各种依赖库,最后代码还不一定跑起来。
如果我是用了docker环境进行项目配置,我只需要将环境打包好后分享给朋友。他只需要安装好显卡驱动就行,什么cuda、pytorch之类的都在我分享的环境了。
实际上github很多项目都提供了docker方式,但是我们更多还是自己配置环境和安装对应的pytorch版本,自己调试代码尝试复现作者的项目。如果你使用了docker,分分钟就能将作者的环境在自己的电脑上复现,非常便捷。
2. 深度学习环境的基本要求
在本文,我将介绍docker的基本使用,以及总结可能遇到的bug的解决方法。
在dockerhub中,有很多现成的镜像可用,本文中会使用anibali/pytorch:1.10.2-cuda11.3-ubuntu20.04分享的镜像。
该镜像是ubuntu20+cuda11.3+pytorch1.10.2,根据描述(ENV NVIDIA_REQUIRE_CUDA=cuda>=11.3 brand=tesla,driver>=418,driver<419 driver>=450)我们只需要本机满足显卡驱动版本即可。其他版本的镜像可以去该作者的主页,他制作了非常多的镜像。
3. Docker的基本操作
3.1 在Windows上安装Docker
windows有桌面docker,所以安装过程比较简单,按照普通软件安装即可。
安装成功后,启动Docker Desktop软件,等待docker引擎启动后,我们就可以在cmd中使用docker命令了。比如执行sudo docker ps -a查看容器,如果没有报错证明ok了,当然现在我们还没有创建容器也不会输出什么有用的,不报错就行。
潜在的bug可能会与WSL有关,需要windows电脑安装有WSL,遇到这类bug可以参看网上的教程。
3.2 在Ubuntu上安装Docker
ubuntu可以通过apt安装,比较简单:
sudo apt-get updatesudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg \lsb-releasecurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpgecho \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/nullsudo apt-get updatesudo apt-get install docker-ce docker-ce-cli containerd.io
然后在终端执行:sudo docker ps -a查看容器,如果没有报错证明ok了,当然现在我们还没有创建容器也不会输出什么有用的,不报错就行。
3.3 拉取一个pytorch的镜像
现在docker安装好了,我们拉取一个上面这个配置好cuda和pytorch的镜像:
docker pull anibali/pytorch:1.10.2-cuda11.3-ubuntu20.04

因为我之前下过,所以显示Already exists。等待镜像拉取完成,如果成功了,我们可以查询所有镜像:
docker image ls

3.4 部署自己的项目
镜像我们有了,现在我们可以创建容器了。
容器就像是一个运行起来虚拟机,我们使用同一个镜像创建不同的容器,就像使用同一个windows系统安装盘(镜像),给不同电脑装系统,这些运行起来的电脑就是容器。注意容器的改变不会影响镜像,如果你在容器里部署好的项目,需要将容器导出为新的镜像分享即可。
创建容器的命令是:
docker run -it --gpus all --name container_name anibali/pytorch:1.10.2-cuda11.3-ubuntu20.04 /bin/bash
在这个命令中,run是创建容器的指令,-it是交互式终端,因为创建的容器就相当于一个本机中的linux服务器,我们可以通过终端与容器交互。–gpus all这个就是使用本机的gpu,–name是给新建容器取个名字, anibali/pytorch:1.10.2-cuda11.3-ubuntu20.04就是要使用的镜像,/bin/bash是指定bash。

可以看到创建成功后,我们就直接进入了容器中,处于容器的/app目录下。
现在我们可以像使用云服务器那样部署自己的项目了,比如在本机终端中(非容器中)使用docker cp 将本机中的项目复制到容器中的/app目录下。

3.5 导出配置好项目的新镜像
现在我们假设你已经在容器中部署好自己的项目了,比如通过python train.py就可以训练,你想让你的朋友也能体验这个项目,那就需要将你的容器打包为镜像分享。
将容器打包为镜像为命令是:
docker commit -m "some information" <容器ID> <image_name:version>

容器ID可以通过docker ps -a查询到,该命令可以查询所有容器信息。
image_name:version就是你自己定义的镜像的名字和版本号。
4. 分享新镜像
现在在本地已经有新镜像了,分享有两种:直接将镜像打包tar分享,或者上传到云,类似本文使用热心作者的镜像那样。
4.1 将镜像导出为tar分享给他人
打包导出的命令:docker save image_naem:version -o output_name.tar
-o就是output,也就是将镜像保存到什么文件。如果不报错在当前目录下能够看到你的镜像tar文件。

他人收到这个tar后,可以通过docker load -i xxx.tar完成加载,如果成功了可以通过docker image ls查看到该镜像。
4.2 或者将镜像推送到云仓库
云仓库可以自己去弄一个,当然dockerhub也可以免费上传分享,前提是你有一个dockerhub的账号。
首先在终端需要登录你的账号:docker login根据提示填写账号和密码。
首先给新镜像打tag:
docker tag new_image:version username/new_image:version
比如sudo docker tag pt_test_image:0 thgpddl/pt_test_image:0
注意,请将thgpddl替换为自己的用户名,然后我们就可以看到新tag的镜像(实际上发现tag的和之前的镜像只是名字不一样,其ID是一样的)

然后开始上传:docker push thgpddl/pt_test_image:0
然后等待上传成功后(不过很可能出现408网络问题,可以尝试开启代理试试),在dockerhub就可以看到上传的镜像了。
5. 使用新镜像
在另一个安装了docker的电脑上使用分享的镜像很简单。如果新镜像上传到了dockerhub,则和拉取镜像一样:docker pull username/image_name:version。
如果是通过save保存到本地的,镜像是一个tar包,则可以在新电脑上通过:docker load -i new_image.tar加载。
6. 跨平台造成nvidia-smi不可用的问题
注意:因为windows的docker底层使用的WSL,和Linux不一样,所以在一个平台制作导出的镜像在另一个平台使用时,可能会出现gpu不可用的问题。比如在Ubuntu系统加载Windows平台导出的镜像时,通过docker run --gpus all创建容器后,在容器中使用nvidia-smi会报错:NVIDIA-SMI couldn't find libnvidia-ml.so library in your system. Please make sure that the NVIDIA Display Driver is properly installed and present in your system.Please also try adding directory that contains li PATH. 那么接下来的内容就会详细如何解决跨平台无法使用GPU的问题
首先会出现问题的情况有(同平台是没有问题的,比如linux和linux,windows和windows):
| 取个名字 | 导出镜像的平台 | 使用镜像的平台 | 问题 |
|---|---|---|---|
| win2linux | Widnows | Ubuntu | 容器内使用nvidia-smi命令报错:NVIDIA-SMI couldn’t find libnvidia-ml.so library in your system. |
| linux2win | Ubuntu | Windows | 创建容器时使用–gpus参数就会报错:libnvidia-ml.so.1- file exists- unknown |
6.1 确认是该问题
我在windows制作的镜像在ubuntu加载后,无法使用nvidia-smi命令并报错NVIDIA-SMI couldn’t find libnvidia-ml.so library in your system.,那么我们需要先确认是不是本节要讨论的问题,所以我们要在容器中查询:
- 显卡是否存在:
lspci | grep -i nvidia(需要安装sudo apt update && sudo apt install pciutils),可以看到存在显卡2208(十六进制),然后在显卡查询查询2208得知是3080ti,就是我的显卡。

- 显卡驱动是否存在:
cat /proc/driver/nvidia/version,可以看到在容器中是可以查询到宿主机的显卡驱动的,证明没问题。
好了,说明显卡和显卡驱动都是正常的,nvida-smi就是不可用

现在请根据自己是哪一个跨平台情况按步骤解决把
6.2 win2linux问题如何解决?
本质问题如图,解决办法就是重新建立软链接,不过方法多样而已。

6.2.1 手动创建软链接
在linux加载来自windows的镜像后,进入容器后使用nvidia-smi命令会报错:

首先查询软链接情况:ldconfig,看到很多libnvidia和libcuda软链接为empty,所以我们目标就是重新建立软链接

进入目录:cd /usr/lib/x86_64-linux-gnu,通过find -name "libnvidia-ml.so"查询显卡驱动515.43.04,请记住这个。

建立libnvidia-ml.so的软链接:
# libnvidia-ml.so.515.43.04 -> libnvidia-ml.so.1
sudo rm -f libnvidia-ml.so.1
sudo ln -s libnvidia-ml.so.515.43.04 libnvidia-ml.so.1
建立libcuda.so的软链接
# libcuda.so.515.43.04->libcuda.so.1
sudo rm -f libcuda.so.1
sudo ln -s libcuda.so.515.43.04 libcuda.so.1
515.43.04是我的本机驱动,请改为自己的。
测试一下:

可以看到nvidias-mi命令可以用了,然后在python中导入torch后创建一个张量放到cuda上去没有报错,说明cuda可用了。
6.2.2 使用Dockfile自动完成
Dockfile就是创建镜像的一种方法,这里大概原理就是在镜像1的基础上,生成镜像2,而在生成过程中自动建立libnvidia-ml.so和libcuda.so的软链接。
注意,与上面方法不同在于,上面的方法是从镜像1创建容器后,到容器里手动创建软链接,然后该容器就可以使用cuda了。本节方法是在镜像1上创建软链接,得到新的镜像,然后就可以直接从镜像创建cuda可用的容器。
那么现在,比如我现在要在linux下使用来自windows的镜像thgpddl/win_1050:0,首先建立createlink.sh文件,内容如下:
# 查找libnvidia-ml.so.driver_version文件,并保存driver_version版本号
libnvidia_ml_file=$(find /usr/lib/x86_64-linux-gnu/ -name 'libnvidia-ml.so.*'|grep -v libnvidia-ml.so.1)
driver_version=${libnvidia_ml_file#/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.}
echo "[success]:find GPU driver version=$driver_version"# 删除libnvidia-ml.so.driver_version.1原本存在的软链接,并且新建软链接:libnvidia-ml.so.1.driver_version -> libnvidia-ml.so.1
rm -f /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1
ln -s "$libnvidia_ml_file" /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1
echo "[success]:create ls: libnvidia-ml.so.1.$driver_version -> libnvidia-ml.so.1"# 删除libcuda.so.driver_version原本存在的软链接,并且新建软链接:libcuda.so.1.driver_version -> libcuda.so.1
rm -f /usr/lib/x86_64-linux-gnu/libcuda.so.1
ln -s "/usr/lib/x86_64-linux-gnu/libcuda.so.1.$driver_version" /usr/lib/x86_64-linux-gnu/libcuda.so.1
echo "[success]:create ls: libcuda.so.1.$driver_version -> libcuda.so.1 -> libcuda.so"
然后在同目录下新建Dockerfile文件(D大写且没有后缀),内容:
FROM thgpddl/win_1050:0 # 优先从docker image找,没有就从dockerhub找WORKDIR /app # 创建工作目录/app
COPY ./createlink.sh . # 将本机的createlink.sh复制到镜像中的/app目录下,注意后面有个点,代表WORKDIR文件夹
USER root # 切换root用户
RUN cd /app && ./createlink.sh # 进入 /app执行createlink.sh
然后创建新镜像:sudo docker build -t new_image_name . 注意最后的点,是指Dockerfile所在的目录(终端应当进入Dockerfile和createlink.sh所在的目录)
该Dockerfile大概意思就是使用thgpddl/win_1050:0作为基础镜像,然后在镜像中创建/app文件夹,然后将createlink.sh复制到镜像里,切换到root用户,进入/app目录并执行createlink.sh自动创建软链接。至此得到软链接已经创建的新镜像了。
在实际使用中,createlink.sh是不用更改的,如果你想分享你的镜像,那么直接给一个文件夹,其中包含createlink.sh和Dockerfile文件,Dockerfile第一行改为你的镜像即可。
6.3 linux2win问题如何解决?
在windows加载来自linux的镜像后,进入容器后使用nvidia-smi命令会报错:

从最后一行大概是说创建这个libnvidia-ml.so.1失败,因为它已经存在。实际上这就是win2linux是我们创建的软链接,可以在windows上它不能覆盖,否则应该能自动覆盖正常运行了。既然windows的docker不能自动覆盖掉,我们帮它删除即可。
基本原理如下,其实无论下面哪种方法都是要删掉两个so软链接。

6.3.1 在WSL使用时手动删除软链接
当然很多时候镜像发布者没有考虑到这个问题,作者在ubuntu下使用–gpus配置好环境后直接发布了,所以我们需要自己去删除libnvidia-ml.so.1和libcuda.so.1文件。
因为启动命令使用–gpus all使用gpu,所以会调用libnvidia-ml.so.1,那么我们不使用gpu,应该能创建容器,然后进去删掉该文件,然后再docker commit为镜像,然后在新镜像就能使用gpu了(此时没有libnvidia-ml.so.1,docker就能创建成功了)
大概意思如下图,镜像1和镜像2的区别在于镜像2删掉了来自ubuntu的libnvidia-ml.so.1(和libcuda.so.1)

首先不使用gpu创建容器:docker run -it --name container_name image_name /bin/bash
然后删除两个so文件:
(cmd) docker run -it --name container_name image_name /bin/bash
(容器内) sudo rm -f /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1
(容器内) sudo rm -f /usr/lib/x86_64-linux-gnu/libcuda.so.1
然后形成新镜像:docker commit -m "some information" container_name new_image_name:0
现在我们得到了一个可以在windows下正常使用的镜像了:
docker run -it --gpus all --name container_name new_image_name:0 /bin/bash
6.3.2 使用Dockerfile自动完成
上节是在非gpu容器中删除两个so.1文件,然后制作为新镜像就可以使用gpu。实际上我们也可以借助Dockerfile来自动在创建新镜像时删除两个so.1文件,一步到位。
Dockerfile文件的内容:
FROM thgpddl/linux2win:0
USER root
RUN rm -rf /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 /usr/lib/x86_64-linux-gnu/libcuda.so.1
然后创建新镜像:sudo docker build -t new_image_name . 注意最后的点,是指Dockerfile所在的目录(终端应当进入Dockerfile所在的目录)
其实该Dockerfile很简单,就是使用基础镜像thgpddl/linux2win:0,然后切换root用户,删除libnvidia-ml.so.1和libcuda.so.1,得到新的镜像文件。
6.3.3 不使用–gpus all的容器打包(针对镜像发布者)
因为linux的镜像在windows使用报错是因为创建libnvidia-ml.so.1失败,因为它已经存在,libnvidia-ml.so.1是在ubuntu中使用gpu创建的。如果ubuntu中不使用gpu,就不会有libnvidia-ml.so.1文件,那么就可以直接在windows上使用而不报错。
其实不用太复杂,我们在ubuntu容器中配置好自己的项目后,然后直接删除两个so.1文件后(确保你不再使用gpu,因为删除后在当前容器就不能使用gpu),直接docker commit导出镜像即可。因为该镜像本身没有两个so.1文件,所以可以直接在Windows或者其他linux中的docker中使用–gpus。
因为ubuntu镜像在windows中报错是因为windows要产生so.1文件,但是ubuntu镜像中存在so.1文件且windows无法强制覆盖。现在好了,我发布镜像时直接打包时删除so.1文件,在win下就不会报错了。
7. 总结
- WSL的镜像在Linux下使用需要设置软链接,Linux镜像在WSL下使用时需要删除软链接。
- libcuda.so.version和libnvidia-ml.so.version,这里的libcuda.so.derver不是安装cuda生产的,而是安装驱动生成的,提供该驱动调用cuda的api。
8. 常见问题debug
- error during connect: in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connectxxxxx:
可能是docker desktop自动更新导致了一些问题,重启docker就好了 - 解决Docker 一直starting 的办法:解决Docker 一直starting 的办法
- WIN10家庭版 找不到Hyper-V的解决办法
- libGL.so.1
一般是安装使用opencv造成的,直接pip install opencv-python-headless - 权限问题,在run指定参数–user=root也是可以解决的,但是可能也是文件夹本身需要chmod改权限
- windows中wsl是默认放在c盘的,非常占用磁盘,【转载】Win10/11 更改 WSL Docker Desktop 存储路径
- docker 问题
不断重启即可,要退出quit那种重启
Reference
win10 WSL2 Docker 与 Linux Docker
WSL2上Docker打包的镜像迁移到Ubuntu服务器上无法使用GPU
libcuda.so.1: cannot open shared object file: No such file or directory
WSL启动nvidia-docker镜像:报错libnvidia-ml.so.1- file exists- unknown
相关文章:
基于Docker的深度学习环境NVIDIA和CUDA部署以及WSL和linux镜像问题
基于Docker的深度学习环境部署 1. 什么是Docker?2. 深度学习环境的基本要求3. Docker的基本操作3.1 在Windows上安装Docker3.2 在Ubuntu上安装Docker3.3 拉取一个pytorch的镜像3.4 部署自己的项目3.5 导出配置好项目的新镜像 4. 分享新镜像4.1 将镜像导出为tar分享给…...
c#中slice,substr,substring区别
1. 都使用一个参数: //栗子数据 var arr [1,2,3,4,5,6,7], str "helloworld!"; //防止空格干扰,不用带空格的,注意这里有个!号也算一位 console.log(str.slice(1)); //elloworld! console.log(str.substring(1)); //…...
java语言里redis在项目中使用场景,每个场景的样例代码
Redis是一款高性能的NoSQL数据库,常被用于缓存、消息队列、计数器、分布式锁等场景。以下是50个Redis在项目中使用的场景以及对应的样例代码和详细说明: ##1、缓存:将查询结果缓存在Redis中,下次查询时直接从缓存中获取ÿ…...
Mongo集合操作
2、创建切换数据库 2.1 默认数据库 mongo数据库和其他类型的数据库一样,可以创建数据库,且可以创建多个数据库。 mongo数据库默认会有四个数据库,分别是 admin:主要存储MongoDB的用户、角色等信息 config:主要存储…...
ConvTranspose2d 的简单例子理解
文章目录 参考基础概念output_padding 简单例子: stride2step1step2step3 参考 逆卷积的详细解释ConvTranspose2d(fractionally-strided convolutions)nn.ConvTranspose2d的参数output_padding的作用torch.nn.ConvTranspose2d Explained 基础概念 逆卷…...
酒精和肠内外健康:有帮助还是有害?
谷禾健康 酒精与健康 饮酒作为一种特殊的文化形式,在我们国家有其独特的地位,在几千年的发展中,酒几乎渗透到日常生活、社会经济、文化活动之中。 据2018年发表的《中国饮酒人群适量饮酒状况》白皮书数据显示,中国饮酒人群高达6亿…...
SylixOS Shell下操作环境变量方法
系统启动后会在内核中生成一份默认的环境变量,环境变量名和默认值由源程序决定。系统启动后如果文件系统中存在有效的/etc/profile文件,则还会自动读取文件中的内容,并导入到Shell环境中,覆盖对应变量或增加新的变量。程序运行时&…...
【dfs解决分组问题-两道例题——供佬学会!】(A元素是放在已经存在的组别中,还是再创建一个更好?--小孩子才做选择,dfs直接两种情况都试试)
问题关键就是: 一个点,可能 新开一个组 比 放到已经存在的组 更划算 因为后面的数据,我们遍历之前的点时,并不知道 所以我们应该针对每个点,都应该做出一个选择就是 新开一个元组或者放到之前的元组中,都尝…...
使用Hexo在Github上搭建个人博客
使用Hexo在Github上搭建个人博客 1. 安装Node和git2. 安装Hexo3. Git与Github的准备工作4. 将Hexo部署到Github5. 开始写作 1. 安装Node和git 在Mac上安装Node.js可以使用Homebrew,使用以下命令安装: brew install node使用以下命令安装Git: …...
【面试题】面试官:说说你对 CSS 盒模型的理解
前言 CSS 盒模型是 CSS 基础的重点难点,因此常被面试官们拿来考察候选人对前端基础的掌握程度,这篇文章将对 CSS 盒模型知识点进行全面的梳理。 我们先看个例子:下面的 div 元素的总宽度是多少呢? js <!DOCTYPE html> &…...
【ROS2】学习笔记
1. 基础概念 1.1 执行单元 1.1.1 executable——执行程序 executable表示针对某个目标的程序执行流程,一个executable可以启动多个node; 1.1.2 node——“进程” node其实就是进程的意思; ROS2允许同时启动两个相同的node,&a…...
Springboot +Flowable,流程表单应用之外置表单(JSON形式)(二)
一.简介 整体上来说,我们可以将Flowable 的表单分为三种不同的类型: 动态表单 这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息,不过不能定义完整的表单页面。外置表单 外置表单我们只需要定义一下表单的 k…...
JavaScript如何使用if语句
JavaScript的if语句可以让我们根据某些条件来执行不同的代码块。使用if语句的基本思路是将要执行的代码放在括号内,并使用if关键字进行匹配。下面是一些例子: 简单的if语句: let age 18; if (age > 18) { console.log("You are…...
XSS攻击以及java应对措施
文章目录 一. XSS攻击介绍1. 前端安全2. xss攻击简介3. xss的攻击方式 二. java应对xss攻击的解决方案1. 强制修改html敏感标签内容2. 利用过滤器过滤非法html标签 一. XSS攻击介绍 1. 前端安全 随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一…...
yolo 训练
这里写目录标题 分配训练集&Validation数量数据集读取读取全部文件夹替换路径 loss weightNMSBBox_IOUEIou Optimizer 分配训练集&Validation数量 validation_size training_size * validation_ratio / (1 - validation_ratio)training_size 219 validation_ratio …...
谷歌chrome浏览器升级新版后字体显示不清楚解决方案
谷歌chrome浏览器升级新版后字体显示不清楚解决方案 参考图片: Chrome更新至版本Chrome 109.0.5414.120 字体看不清 浏览器症状与表现 Chrome更新至版本Chrome 109.0.5414.120 字体看不清;会很细,在设置中选择自定义的字体,仍无法…...
在外包干了三年,我废了……不吹不黑!
没错,我也干过外包,一干就是三年,三年后,我废了…… 虽说废的不是很彻底,但那三年我几乎是出差了三年、玩了三年、荒废了三年,那三年,我的技术能力几乎是零成长的。 说起这段三年的外包经历&a…...
【Vue】学习笔记-消息的订阅与发布
消息的订阅与发布(基本不用) 消息订阅与发布(pubsub)消息订阅与发布是一种组件间的通信的方式,适用于任意组件间通信 消息订阅与发布 1.订阅消息∶消息名 2.发布消息︰消息内容 消息订阅与发布的工作流程: (A是订阅者,B是发布…...
大疆无人机 MobileSDK(遥控器/手机端)开发 v5版<1>
文章目录 概要整体架构流程技术细节SDK 架构体系概述层级架构智能任务空白项目集成 MSDK新建空白项目新建 MyApplication.kt 文件修改 build.gradle(Module) 文件修改 AndroidManifest.xml 文件修改 MainActivity.kt 文件导入 UXSDK 开源框架4.X 和 5.X 版本差异说明DJIKey差异…...
azkaban介绍
目录 为什么需要工作流调度系统 什么是azkaban azkaban适用场景 azkaban特点 常见的工作流调度系统 azkaban和Ooize特性对比 azkaban的架构 azkaban调度的任务有可能有那些类型 总结 为什么需要工作流调度系统 一个完整的大数据分析系统,必然由很多任务单…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
GeoServer发布PostgreSQL图层后WFS查询无主键字段
在使用 GeoServer(版本 2.22.2) 发布 PostgreSQL(PostGIS)中的表为地图服务时,常常会遇到一个小问题: WFS 查询中,主键字段(如 id)莫名其妙地消失了! 即使你在…...
Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...
