Conda - 如何在现有环境中仅更新 cudatoolkit?

Conda - how to update only cudatoolkit in an existing environment?

这是我在使用 conda 更新包时 运行 遇到的一般问题的具体实例。 我有一个在机器 A 上运行良好的环境。我想将它转移到机器 B。 但是,机器 A 有 GTX1080 gpus,由于配置我无法控制,需要 cudatoolkit 10.2。 机器B有A100 gpus,由于配置我无法控制,需要cudatoolkit 11.1

我可以轻松地将机器 A 的环境导出到 yml,并使用该 yml 在机器 B 上创建一个新环境。 但是,我似乎无法在机器 B 的那个环境中将 cudatoolkit 更新到 11.1。 我试试

conda install cudatoolkit=11.1 -c conda-forge

我遇到了约 5 分钟的冲突和重试解决消息,这些消息最终并没有真​​正告诉我任何有用的信息(抱歉,我没有在 post 中捕获它,它非常庞大).

如果不能在机器 B 上从头开始重新创建环境,有没有办法将 cudatoolkit 更新到该机器的 GPU 所需的版本?

我也试过 conda update ... 的各种排列,但都没有成功。

如果有帮助,这里是机器 A 的 yml 文件:

name: VAE180
channels:
  - pytorch
  - conda-forge
  - defaults
dependencies:
  - _libgcc_mutex=0.1=main
  - absl-py=0.12.0=pyhd8ed1ab_0
  - aiohttp=3.7.4=py38h27cfd23_1
  - argh=0.26.2=pyh9f0ad1d_1002
  - async-timeout=3.0.1=py_1000
  - attrs=20.3.0=pyhd3deb0d_0
  - blas=1.0=mkl
  - blinker=1.4=py_1
  - brotlipy=0.7.0=py38h8df0ef7_1001
  - bzip2=1.0.8=h7b6447c_0
  - c-ares=1.17.1=h36c2ea0_0
  - ca-certificates=2020.12.5=ha878542_0
  - cachetools=4.2.1=pyhd8ed1ab_0
  - certifi=2020.12.5=py38h578d9bd_1
  - cffi=1.14.5=py38h261ae71_0
  - chardet=3.0.4=py38h924ce5b_1008
  - click=7.1.2=pyh9f0ad1d_0
  - cloudpickle=1.6.0=py_0
  - configparser=5.0.2=pyhd8ed1ab_0
  - cryptography=3.4.6=py38ha5dfef3_0
  - cudatoolkit=10.2.89=hfd86e86_1
  - cycler=0.10.0=py38_0
  - dbus=1.13.18=hb2f20db_0
  - docker-pycreds=0.4.0=py_0
  - expat=2.2.10=he6710b0_2
  - ffmpeg=4.3=hf484d3e_0
  - fontconfig=2.13.1=h6c09931_0
  - freetype=2.10.4=h5ab3b9f_0
  - fsspec=0.8.7=pyhd8ed1ab_0
  - future=0.18.2=py38h578d9bd_3
  - gitdb=4.0.5=pyhd8ed1ab_1
  - gitpython=3.1.14=pyhd8ed1ab_0
  - glib=2.67.4=h36276a3_1
  - gmp=6.2.1=h2531618_2
  - gnutls=3.6.5=h71b1129_1002
  - google-auth=1.24.0=pyhd3deb0d_0
  - google-auth-oauthlib=0.4.1=py_2
  - gql=0.1.0=py_0
  - graphql-core=3.1.3=pyhd8ed1ab_0
  - grpcio=1.33.2=py38heead2fc_2
  - gst-plugins-base=1.14.0=h8213a91_2
  - gstreamer=1.14.0=h28cd5cc_2
  - gym=0.18.0=py38h81c977d_0
  - icu=58.2=he6710b0_3
  - idna=2.10=pyh9f0ad1d_0
  - importlib-metadata=3.7.3=py38h578d9bd_0
  - intel-openmp=2020.2=254
  - joblib=1.0.1=pyhd3eb1b0_0
  - jpeg=9b=h024ee3a_2
  - kiwisolver=1.3.1=py38h2531618_0
  - lame=3.100=h7b6447c_0
  - lcms2=2.11=h396b838_0
  - ld_impl_linux-64=2.33.1=h53a641e_7
  - libffi=3.3=he6710b0_2
  - libgcc-ng=9.1.0=hdf63c60_0
  - libgfortran-ng=7.3.0=hdf63c60_0
  - libiconv=1.15=h63c8f33_5
  - libpng=1.6.37=hbc83047_0
  - libprotobuf=3.14.0=h8c45485_0
  - libstdcxx-ng=9.1.0=hdf63c60_0
  - libtiff=4.2.0=h3942068_0
  - libuuid=1.0.3=h1bed415_2
  - libuv=1.40.0=h7b6447c_0
  - libwebp-base=1.2.0=h27cfd23_0
  - libxcb=1.14=h7b6447c_0
  - libxml2=2.9.10=hb55368b_3
  - lz4-c=1.9.3=h2531618_0
  - markdown=3.3.4=pyhd8ed1ab_0
  - matplotlib=3.3.4=py38h06a4308_0
  - matplotlib-base=3.3.4=py38h62a2d02_0
  - mkl=2020.2=256
  - mkl-service=2.3.0=py38he904b0f_0
  - mkl_fft=1.3.0=py38h54f3939_0
  - mkl_random=1.1.1=py38h0573a6f_0
  - multidict=5.1.0=py38h27cfd23_2
  - ncurses=6.2=he6710b0_1
  - nettle=3.4.1=hbb512f6_0
  - ninja=1.10.2=py38hff7bd54_0
  - numpy=1.19.2=py38h54aff64_0
  - numpy-base=1.19.2=py38hfa32c7d_0
  - nvidia-ml=7.352.0=py_0
  - oauthlib=3.0.1=py_0
  - olefile=0.46=py_0
  - openh264=2.1.0=hd408876_0
  - openssl=1.1.1j=h27cfd23_0
  - packaging=20.9=pyh44b312d_0
  - pandas=1.2.3=py38ha9443f7_0
  - pathtools=0.1.2=py_1
  - pcre=8.44=he6710b0_0
  - pillow=8.1.2=py38he98fc37_0
  - pip=21.0.1=py38h06a4308_0
  - promise=2.3=py38h578d9bd_3
  - protobuf=3.14.0=py38h2531618_1
  - psutil=5.7.3=py38h8df0ef7_0
  - pyasn1=0.4.8=py_0
  - pyasn1-modules=0.2.7=py_0
  - pycparser=2.20=pyh9f0ad1d_2
  - pyglet=1.5.15=py38h578d9bd_0
  - pyjwt=2.0.1=pyhd8ed1ab_0
  - pyopenssl=20.0.1=pyhd8ed1ab_0
  - pyparsing=2.4.7=pyh9f0ad1d_0
  - pyqt=5.9.2=py38h05f1152_4
  - pysocks=1.7.1=py38h578d9bd_3
  - python=3.8.8=hdb3f193_4
  - python-dateutil=2.8.1=pyhd3eb1b0_0
  - python_abi=3.8=1_cp38
  - pytorch=1.8.0=py3.8_cuda10.2_cudnn7.6.5_0
  - pytorch-lightning=1.2.4=pyhd8ed1ab_0
  - pytz=2021.1=pyhd3eb1b0_0
  - pyyaml=5.3.1=py38h8df0ef7_1
  - qt=5.9.7=h5867ecd_1
  - readline=8.1=h27cfd23_0
  - requests=2.25.1=pyhd3deb0d_0
  - requests-oauthlib=1.3.0=pyh9f0ad1d_0
  - rsa=4.7.2=pyh44b312d_0
  - scikit-learn=0.24.1=py38ha9443f7_0
  - scipy=1.6.1=py38h91f5cce_0
  - sentry-sdk=0.20.3=pyh44b312d_0
  - setuptools=52.0.0=py38h06a4308_0
  - shortuuid=1.0.1=py38h578d9bd_4
  - sip=4.19.13=py38he6710b0_0
  - six=1.15.0=py38h06a4308_0
  - smmap=3.0.5=pyh44b312d_0
  - sqlite=3.35.2=hdfb4753_0
  - subprocess32=3.5.4=py_1
  - tensorboard=2.4.1=pyhd8ed1ab_0
  - tensorboard-plugin-wit=1.8.0=pyh44b312d_0
  - tensorboardx=2.1=py_0
  - threadpoolctl=2.1.0=pyh5ca1d4c_0
  - tk=8.6.10=hbc83047_0
  - torchaudio=0.8.0=py38
  - torchvision=0.9.0=py38_cu102
  - tornado=6.1=py38h27cfd23_0
  - tqdm=4.59.0=pyhd8ed1ab_0
  - typing-extensions=3.7.4.3=0
  - typing_extensions=3.7.4.3=py_0
  - urllib3=1.26.4=pyhd8ed1ab_0
  - wandb=0.10.20=pyhd8ed1ab_0
  - watchdog=0.10.4=py38h578d9bd_0
  - werkzeug=1.0.1=pyh9f0ad1d_0
  - wheel=0.36.2=pyhd3eb1b0_0
  - xz=5.2.5=h7b6447c_0
  - yaml=0.2.5=h516909a_0
  - yarl=1.6.3=py38h25fe258_0
  - zipp=3.4.1=pyhd8ed1ab_0
  - zlib=1.2.11=h7b6447c_3
  - zstd=1.4.5=h9ceee32_0
  - pip:
    - pytorch-lightning-bolts==0.3.0
prefix: /home/eric/miniconda3/envs/VAE180

限制过度

我认为问题是,从包含版本和构建的 YAML 重新创建会将这些版本和构建建立为该环境向前发展的明确规范。也就是说,Conda 会将显式规范视为它无法更改的硬性要求,因此即使 cudatoolkit 的单个依赖项也需要更新才能使用版本 11,Conda 将不知道如何满足它不会违反先前指定的约束。

具体是我搜索时看到的(假设linux-64平台):

$ conda search --info 'cudatoolkit[subdir="linux-64",version="11.1.*"]'
Loading channels: done
...

cudatoolkit 11.1.1 h6406543_8
-----------------------------
file name   : cudatoolkit-11.1.1-h6406543_8.tar.bz2
name        : cudatoolkit
version     : 11.1.1
build       : h6406543_8
build number: 8
size        : 1.20 GB
license     : NVIDIA End User License Agreement
subdir      : linux-64
url         : https://conda.anaconda.org/conda-forge/linux-64/cudatoolkit-11.1.1-h6406543_8.tar.bz2
md5         : 4851e7f19b684e517dc8e6b5b375dda0
timestamp   : 2021-02-12 16:31:01 UTC
constraints : 
  - __cuda >=11.1
dependencies: 
  - __glibc >=2.17,<3.0.a0
  - libgcc-ng >=9.3.0
  - libstdcxx-ng >=9.3.0

请注意依赖项如何与您的 YAML 规范冲突。也就是说,YAML 将 libgcc-nglibstdcxx-ng 锁定到版本 9.1.0,而 cudatoolkit==11.1.1 需要版本 9.3.0 或更高版本。

最低限度的放松

仅编辑上述规格可能就足够了。但是,没有简单的方法可以判断这是否会与其他内容发生冲突。不过值得一试。也就是说,将 YAML 编辑为:

dependencies:
...
  - cudatoolkit=11.1
  - libgcc-ng
  - libstdcxx-ng
...

放弃对依赖项的约束,让 Conda 解决它们。

自由约束

一种更自由的导出环境的方法是使用 --from-history 标志:

conda env export --from-history -n VAE180 > VAE180.minimal.yaml

这只会从用户历史记录中导出显式约束,其中可能包括也可能不包括版本和构建,具体取决于用户最初创建环境的方式。通常,它比默认导出生成的内容受到的限制要少得多。然后可以编辑此 YAML 以具有 cudatoolkit=11.1,然后尝试用它创建环境。

这种方法的缺点是许多其他软件包可能会采用更新的版本,因此它不像以前那样忠实地复制原始环境。

基本上,我总是会为新的 A100 重新安装新的 11.1 Conda 环境。 Conda 将安装几乎所有你需要的东西。然后,您可以为您的项目安装额外的包。额外包裹的数量对我来说并不多。即使是 torch 或 tf env,或所有 scipy/pandas/sklearn 堆栈都会花费您很长时间。