通过torch.empty来看pytorch的broadcast机制

本文深入探讨了PyTorch中的广播机制,通过对比可进行相加与不可进行相加的Tensor实例,详细解析了Tensor维度匹配原则及BroadcastingSemantics在实际应用中的表现。
部署运行你感兴趣的模型镜像

示例一:可以进行相加的tensor

from __future__ import print_function
import torch # 找不到torch模块是因为对应的解释器中没有torch模块
# File-Settings-grammer_learning-Project Interpreter:进行更换即可


x=torch.empty((6,1,2))
z=torch.empty((1,2,2))
c=x+z
print(c)
print(x)
y=torch.empty(2,3)
print(y)

输出结果如下:

D:\Anaconda3\envs\pytorch_1.4_python_3.6_CUDA_10.1\python.exe E:/【Developer】/python/deeplearning_programs/grammar_learning/test/env_validate.py
tensor([[[ 0.0000e+00,  0.0000e+00],
         [ 0.0000e+00,  0.0000e+00]],

        [[ 0.0000e+00,  0.0000e+00],
         [ 0.0000e+00,  0.0000e+00]],

        [[ 0.0000e+00,  0.0000e+00],
         [ 0.0000e+00,  0.0000e+00]],

        [[-1.5004e-16,  4.5915e-41],
         [-1.5004e-16,  4.5915e-41]],

        [[-1.5034e-16,  4.5915e-41],
         [-1.5034e-16,  4.5915e-41]],

        [[ 2.4263e-29,  4.5262e-43],
         [ 2.4263e-29,  4.5262e-43]]])
tensor([[[ 0.0000e+00,  0.0000e+00]],

        [[ 0.0000e+00,  0.0000e+00]],

        [[ 0.0000e+00,  0.0000e+00]],

        [[-1.5004e-16,  4.5915e-41]],

        [[-1.5034e-16,  4.5915e-41]],

        [[ 2.4263e-29,  4.5262e-43]]])
tensor([[4.3697e-29, 4.5262e-43, 1.7796e-43],
        [0.0000e+00, 0.0000e+00, 0.0000e+00]])

Process finished with exit code 0

分析如下:

  1. 前提说明:torch.empty函数用来返回一个未初始化的tensor,其具体的解释说明参见下图:
    在这里插入图片描述
  2. 首先定义了一个维度为(6,1,2)的变量x,然后定义了一个维度为(1,2,2)的变量z,然后进行相加得到并且输出c,如上所示:在命令行中输出说明程序可正常运行

示例二:不可以进行相加的tensor

还是上面的程序,但是将x的维度进行相应的更改,改成(6,3,2),程序如下:

from __future__ import print_function
import torch # 找不到torch模块是因为对应的解释器中没有torch模块
# File-Settings-grammer_learning-Project Interpreter:进行更换即可


x=torch.empty((6,3,2))
z=torch.empty((1,2,2))
c=x+z
print(c)
print(x)
y=torch.empty(2,3)
print(y)

输出结果如下:

D:\Anaconda3\envs\pytorch_1.4_python_3.6_CUDA_10.1\python.exe E:/【Developer】/python/deeplearning_programs/grammar_learning/test/env_validate.py
Traceback (most recent call last):
  File "E:/【Developer】/python/deeplearning_programs/grammar_learning/test/env_validate.py", line 8, in <module>
    c=x+z
RuntimeError: The size of tensor a (3) must match the size of tensor b (2) at non-singleton dimension 1

Process finished with exit code 1

如上所示:解释器告诉我们,tensor x在维度1上的值3和tensor z在维度1上的值不匹配,报了一个RuntimeError。为什么呢,主要是torch的broadcasting机制的原因,详见原因分析。

原因分析

示例二中不能进行tensor x和z进行相加的原因是torch的broadcast机制不允许其进行操作,具体原因可以查看官网 Broadcasting Semantics,以下是我的截图:
在这里插入图片描述
如图所示,如何判定一个tensor是否是“broadcastable(可传播的)”需满足以下两个条件:

  1. 每一个tensor至少有一个维度
  2. 当开始从维度上进行迭代(可以理解为遍历,因为要遍历每一个维度然后进行相应的计算)时,从最尾端的维度开始,在每一个被遍历到的维度上的大小必须满足要么相等、其中一个tensor的该维度大小为1或者其中一个tensor在该维度上的大小不存在

根据以上两个条件,我们回过去看“示例二:不可以进行相加的tensor”,tensor x和tensor z在维度2(最尾端维度)上具有相同的大小2,所以该维度上可以进行相加操作且不会报错,但是在维度1上tensor x的大小为3,维度1上tensor z的大小为2,所以解释器曝出了RuntimeError,如示例二中输出结果如下中所示。
本模块中的截图中的示例代码中也给出了相关的判断tensor是否是“broadcastable”的相关示例,可以仔细思考一下,手写python程序验证一下。

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

### PyTorch `torch.distributed.all_gather_into_tensor` 使用方法和实现细节 #### 1. 函数定义与功能 `torch.distributed.all_gather_into_tensor` 是 PyTorch 分布式通信库中的一个函数,用于在多个进程中将所有进程的张量数据收集到一个连续的张量中。与 `all_gather` 不同,该函数直接将结果写入到用户提供的输出张量中,从而避免了额外的内存分配[^3]。 函数签名如下: ```python torch.distributed.all_gather_into_tensor(output_tensor, input_tensor, group=None, async_op=False) ``` - **`output_tensor`**: 输出张量,其形状应为 `[world_size * input_tensor.shape]`,即包含所有进程的输入张量数据。 - **`input_tensor`**: 每个进程的输入张量。 - **`group`**: 可选参数,指定执行操作的进程组。如果为 `None`,则默认使用全局进程组[^3]。 - **`async_op`**: 如果为 `True`,则操作将以异步方式执行,并返回一个工作句柄(`work handle`)。如果为 `False`,则操作是同步的[^3]。 #### 2. 示例代码 以下是一个简单的示例,展示如何使用 `all_gather_into_tensor`: ```python import torch import torch.distributed as dist # 初始化分布式环境 dist.init_process_group(backend='nccl', init_method='env://', world_size=2, rank=0) # 创建输入张量 input_tensor = torch.tensor([dist.get_rank() + 1], device='cuda') # 创建输出张量,大小为 [world_size * input_tensor.shape] world_size = dist.get_world_size() output_tensor = torch.empty([world_size], dtype=input_tensor.dtype, device='cuda') # 执行 all_gather_into_tensor dist.all_gather_into_tensor(output_tensor, input_tensor) # 打印结果 print(f"Rank {dist.get_rank()}, output_tensor: {output_tensor}") ``` #### 3. 实现细节 `all_gather_into_tensor` 的核心思想是通过点对点通信(如 `send` 和 `recv`)或集合通信(如 `broadcast` 和 `gather`)来实现跨进程的数据交换。以下是其实现的关键点: - **内存优化**: 与传统的 `all_gather` 不同,`all_gather_into_tensor` 不会创建新的张量来存储结果,而是直接将结果写入到用户提供的 `output_tensor` 中。这减少了内存分配开销,提高了性能[^4]。 - **异步支持**: 当设置 `async_op=True` 时,函数不会阻塞当前线程,而是返回一个工作句柄,允许用户在后台完成操作的同时执行其他任务[^4]。 - **后端依赖**: 该函数依赖于底层通信后端(如 NCCL、Gloo 或 MPI),具体实现由后端决定。例如,在 NCCL 后端中,`all_gather_into_tensor` 通常会被映射到 NCCL 的 `ncclAllGather` 原语[^5]。 #### 4. 注意事项 - **张量形状匹配**: 输入张量和输出张量的形状必须满足特定要求。输入张量在所有进程中必须具有相同的形状和数据类型,而输出张量的大小应为 `world_size * input_tensor.size()`[^3]。 - **设备一致性**: 输入张量和输出张量必须位于同一设备上(如 GPU 或 CPU),并且与通信后端兼容[^3]。 - **分布式环境初始化**: 在调用 `all_gather_into_tensor` 之前,必须正确初始化分布式环境并加入相应的进程组[^3]。 ```python dist.init_process_group(backend='nccl', init_method='env://', world_size=2, rank=0) ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值