Change:
Currently, you can have a libnccl on your system, and pytorch setup favors that instead of compiling one itself from source. The code that takes care of this is: However, this breaks gloo build because gloo gets a path to NCCL via:
I got the error during the installation: Is it related to this problem?
that's a dupe of
no, that's a consequence of , now you have to do before compiling. I think you don't want to do recursive submodule update, because that will pull in gtest and another copy of nccl.
Alternatively we can pass new flags to gloo to prevent it from using its own NCCL
Thanks works for me.
You can prevent it from using its own nccl, but its cmake still has to be able to find some nccl.
I think should be sufficient. I'm testing.
fixes it when we dont have an external NCCL and pytorch compiles it's own NCCL?
I don't see how NCCLEXTERNAL fixes anything, looks like in gloo NCCLEXTERNAL is used just to set dependency if gloo is compiling its own nccl (which we don't want in any case).
The only thing I tested when I was that the vendored nccl was not being built (even if its submodule was checked out); I tested this by adding an to one of the headers. I'll test with the other configurations.
Actually, there are a few bugs here. First, even though GLOOFLAGS looks like it's setting NCCLROOTDIR: it actually isn't because the gloo invocation is which expands to but only is passed to cmake. Suppose you fix this. nccl is still not going to be picked up, because INSTALLDIR is PyTorch's local install dir, but if you disabled nccl builds, there will never actually be a nccl here. So cmake is just going to do it's standard search to find a nccl somewhere. Inversely, if you ever built nccl, and then turn it off, we will keep picking up that locally built version until you delete it. So we shouldn't do that. Suppose you fix this. Then I think gloo will (continue to) correctly pick up system nccl and be built with it, and the final thing to fix is that build of PyTorch csrc doesn't know how to search for nccl headers somewhere. This is probably related to . I wonder, maybe we shouldn't do any autodetection at all, and force the user to pass us the include and library paths of nccl if they want to build with system.
FYI, I committed a change to gloo to stop bundling NCCL itself. It will now happily pick up whatever NCCL you give it through NCCLROOTDIR or by trying to find it in the standard systems paths. See facebookincubator/gloo You do have to set to make Gloo try and find it and compile in support.
So to fix this, you should be able to not specify anything aside from if you want to use system NCCL, and add if you have some custom location (either a PyTorch bundled version or a custom install altogether).

Discussion:
from tools.setup_helpers.env import check_env_flag from tools.setup_helpers.cuda import WITH_CUDA, CUDA_HOME from tools.setup_helpers.cudnn import WITH_CUDNN, CUDNN_LIB_DIR, CUDNN_INCLUDE_DIR <ins> from tools.setup_helpers.nccl import WITH_NCCL, WITH_SYSTEM_NCCL, NCCL_LIB_DIR, NCCL_INCLUDE_DIR, NCCL_ROOT_DIR </ins> from tools.setup_helpers.split_types import split_types DEBUG = check_env_flag('DEBUG') WITH_DISTRIBUTED = not check_env_flag('NO_DISTRIBUTED') WITH_DISTRIBUTED_MW = WITH_DISTRIBUTED and check_env_flag('WITH_DISTRIBUTED_MW') <del> WITH_NCCL = WITH_CUDA and platform.system() != 'Darwin' SYSTEM_NCCL = False </del> ################################################################################

build_libs_cmd = ['bash', 'torch/lib/build_libs.sh'] my_env = os.environ.copy() my_env["PYTORCH_PYTHON"] = sys.executable <ins> if WITH_SYSTEM_NCCL: my_env["NCCL_ROOT_DIR"] = NCCL_ROOT_DIR </ins> if WITH_CUDA: build_libs_cmd += ['--with-cuda'] if subprocess.call(build_libs_cmd + libs, env=my_env) != 0:

libs = ['TH', 'THS', 'THNN'] if WITH_CUDA: libs += ['THC', 'THCS', 'THCUNN'] <del> if WITH_NCCL and not SYSTEM_NCCL: </del> <ins> if WITH_NCCL and not WITH_SYSTEM_NCCL: </ins> libs += ['nccl'] libs += ['THPP', 'libshm', 'ATen', 'nanopb'] if WITH_DISTRIBUTED:

print('-- Detected CUDA at ' + CUDA_HOME) else: print('-- Not using CUDA') <del> if WITH_NCCL and SYSTEM_NCCL: print('-- Using system provided NCCL library') </del> <ins> if WITH_NCCL and WITH_SYSTEM_NCCL: print('-- Using system provided NCCL library at ' + NCCL_LIB_DIR + ', ' + NCCL_INCLUDE_DIR) </ins> elif WITH_NCCL: print('-- Building NCCL library') else:

# static library only NANOPB_STATIC_LIB = os.path.join(lib_path, 'libprotobuf-nanopb.a') <del> if WITH_NCCL and (subprocess.call('ldconfig -p | grep libnccl >/dev/null', shell=True) == 0 or subprocess.call('/sbin/ldconfig -p | grep libnccl >/dev/null', shell=True) == 0): SYSTEM_NCCL = True </del> main_compile_args = ['-D_THP_CORE'] main_libraries = ['shm'] main_link_args = [TH_LIB, THS_LIB, THNN_LIB, ATEN_LIB, NANOPB_STATIC_LIB]

main_sources += split_types("torch/csrc/cuda/Tensor.cpp") if WITH_NCCL: <del> if SYSTEM_NCCL: </del> <ins> if WITH_SYSTEM_NCCL: </ins> main_libraries += ['nccl'] <ins> include_dirs.append(NCCL_INCLUDE_DIR) library_dirs.append(NCCL_LIB_DIR) </ins> else: main_link_args += [NCCL_LIB] extra_compile_args += ['-DWITH_NCCL']

<ins> import os import sys import glob import platform import warnings from itertools import chain from .env import check_env_flag from .cuda import WITH_CUDA, CUDA_HOME def gather_paths(env_vars): return list(chain(*(os.getenv(v, '').split(':') for v in env_vars))) is_conda = 'conda' in sys.version or 'Continuum' in sys.version conda_dir = os.path.join(os.path.dirname(sys.executable), '..') WITH_NCCL = WITH_CUDA and platform.system() != 'Darwin' WITH_SYSTEM_NCCL = False NCCL_LIB_DIR = None NCCL_INCLUDE_DIR = None NCCL_ROOT_DIR = None if WITH_CUDA and not check_env_flag('NO_SYSTEM_NCCL'): ENV_ROOT = os.getenv('NCCL_ROOT_DIR', None) # NCCL_ROOT_DIR takes precedence over NCCL_LIB_DIR lib_paths = list(filter(bool, [ os.path.join(ENV_ROOT, 'lib') if ENV_ROOT is not None else None, os.path.join(ENV_ROOT, 'lib64') if ENV_ROOT is not None else None, os.getenv('NCCL_LIB_DIR'), os.path.join(CUDA_HOME, 'lib'), os.path.join(CUDA_HOME, 'lib64'), '/usr/lib/x86_64-linux-gnu/', '/usr/lib/powerpc64le-linux-gnu/', '/usr/lib/aarch64-linux-gnu/', ] + gather_paths([ 'LIBRARY_PATH', ]) + gather_paths([ 'LD_LIBRARY_PATH', ]))) if os.getenv('NCCL_INCLUDE_DIR') is not None: warnings.warn("Ignoring environment variable NCCL_INCLUDE_DIR because " "NCCL_INCLUDE_DIR is implicitly assumed as " "$NCCL_ROOT_DIR/include or $NCCL_LIB_DIR/../include") if is_conda: lib_paths.append(os.path.join(conda_dir, 'lib')) for path in lib_paths: if path is None or not os.path.exists(path): continue if glob.glob(os.path.join(path, 'libnccl*')): if os.path.exists((os.path.join(path, '../include/nccl.h'))): NCCL_LIB_DIR = path NCCL_INCLUDE_DIR = path break if NCCL_LIB_DIR is not None: WITH_SYSTEM_NCCL = True NCCL_ROOT_DIR = os.path.abspath(os.path.join(NCCL_LIB_DIR, "../")) </ins>