【问题标题】:Python multiprocessing on multiple CPUs, GPUs多 CPU、GPU 上的 Python 多处理
【发布时间】:2021-07-25 12:47:53
【问题描述】:

我有 8 个 GPU,64 个 CPU 内核 (multiprocessing.cpu_count()=64)

我正在尝试使用深度学习模型推断多个视频文件。我希望在 8 个 GPU 中的每一个上处理一些文件。对于每个 GPU,我希望使用不同的 6 个 CPU 内核。

python 文件名下方:inference_{gpu_id}.py

Input1: GPU_id

Input2: Files to process for GPU_id

from torch.multiprocessing import Pool, Process, set_start_method
try:
     set_start_method('spawn', force=True)
except RuntimeError:
    pass

model = load_model(device='cuda:' + gpu_id) 

def pooling_func(file):
    preds = []
    cap = cv2.VideoCapture(file)
    while(cap.isOpened()):
          ret, frame = cap.read()
          count += 1
          if ret == True:
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                pred = model(frame)[0]
                preds.append(pred)
          else:
                break
    cap.release()
    np.save(file[:-4]+'.npy', preds)

def process_files():

    # all files to process on gpu_id
    files = np.load(gpu_id + '_files.npy') 

    # I am hoping to use 6 cores for this gpu_id, 
    # and a different 6 cores for a different GPU id
    pool = Pool(6) 

    r = list(tqdm(pool.imap(pooling_func, files), total = len(files)))
    pool.close()
    pool.join()

if __name__ == '__main__':
    import multiprocessing
    multiprocessing.freeze_support()
    process_files()

我希望同时在所有 GPU 上运行 inference_{gpu_id}.py 文件

目前,我能够在一个 6 核的 GPU 上成功运行它,但是当我尝试在所有 GPU 上一起运行它时,只有 GPU 0 运行,所有其他都停止给出以下错误消息。

RuntimeError: CUDA error: invalid device ordinal.

我正在运行的脚本:

CUDA_VISIBLE_DEVICES=0 inference_0.py

CUDA_VISIBLE_DEVICES=1 inference_1.py

...

CUDA_VISIBLE_DEVICES=7 inference_7.py

【问题讨论】:

  • 你试过os.environ["CUDA_VISIBLE_DEVICES"]=str(gpu_id)吗?
  • 只需使用device='cuda'
  • @natthaphon 成功了,谢谢 :)
  • @Ivan 我删除了另一个问题,因为这个问题有更多细节
  • 是的,我明白,很抱歉。感谢您的详细回答:)

标签: python pytorch python-multiprocessing multiprocess cpu-cores


【解决方案1】:

以下最初是对question you asked的回复,但后来被删除了。


考虑到这一点,如果您没有使用 CUDA_VISIBLE_DEVICES 标志,那么所有 GPU 都可用于您的 PyTorch 进程。这意味着torch.cuda.device_count 将返回 8(假设您的版本设置有效)。您将能够通过torch.devicetorch.device('cuda:0')torch.device('cuda:1')、...和torch.device('cuda:8') 访问这8 个GPU 中的每一个。

现在,如果您只打算使用一个并且希望将您的流程限制为一个。然后CUDA_VISIBLE_DEVICES=i(其中i 是设备序号)会这样做。在这种情况下,torch.cuda 只能通过torch.device('cuda:0') 访问单个设备。实际的设备序号是什么并不重要,您访问它的方式是通过torch.device('cuda:0')

如果您允许访问多个设备:假设 n°0、n°4 和 n°2,那么您将使用CUDA_VISIBLE_DEVICES=0,4,2。因此,您通过d0 = torch.device('cuda:0')d1 = torch.device('cuda:1')d2 = torch.device('cuda:2') 引用您的cuda 设备。与您使用标志定义它们的顺序相同,

d0 -> GPU n°0、d1 -> GPU n°4 和 d2 -> GPU n°2。

这样您就可以使用相同的代码并在不同的 GPU 上运行它而无需更改您引用设备序号的底层代码

总而言之,您需要查看的是运行代码所需的设备数量。在您的情况下:1 就足够了。您将使用torch.device('cuda:0') 引用它。但是,在运行代码时,您需要使用以下标志指定 cuda:0 设备是什么:

> CUDA_VISIBLE_DEVICES=0 inference.py
> CUDA_VISIBLE_DEVICES=1 inference.py
  ...
> CUDA_VISIBLE_DEVICES=7 inference.py

请注意'cuda' 将默认为'cuda:0'

【讨论】:

  • 我试过了,它可以工作,但时间很慢,不知道为什么。如果我在一个 GPU 上运行,则需要 3 秒/次迭代,但如果我尝试在所有 GPU 上一起运行,则在每个 GPU 上需要 30 秒/次迭代
  • 这可能与您的数据加载器有关。
  • 现在没有数据加载器,我只是在读取视频文件,做一些处理,再写回一个新的视频文件
  • 不,我的意思是数据加载过程——无论你是否实际使用 DataLoader——都需要时间。如果您同时运行许多训练,则会导致 CPU 过载,因为处理所有这些数据读取会更加困难。
  • 那么有什么技巧可以加快这个过程吗?
猜你喜欢
  • 2018-05-26
  • 2015-02-26
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 2015-07-17
相关资源
最近更新 更多