Pytorch中x.cuda(non_blocking=True)参数解释

PyTorch的x.cuda(non_blocking=True)参数用于实现异步数据传输,提高计算效率。在数据从CPU到GPU的迁移过程中,非阻塞模式允许主机不等待数据完全加载即可继续执行其他任务,但可能在某些情况下导致性能下降或错误。使用异步传输时,需注意配合torch.cuda.synchronize()确保数据完整性,或使用CUDAStream管理操作顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pytorch中x.cuda(non_blocking=True)参数解释


在 PyTorch 中, non_blocking 是一个布尔类型的参数,用于指定是否启用异步数据传输。当你将 Tensor 数据从 CPU 移动到 GPU 时,可以通过设置 non_blocking=True 来启用异步传输模式,从而提高计算效率。

在使用 PyTorch 进行深度学习时,通常需要将数据从主机内存转移到 GPU 硬件设备上进行加速计算,这个过程称为数据的迁移或者拷贝(copy)。如果将数据迁移至 GPU 设备时使用默认设置,则表示该操作是同步的,即数据迁移完成后会阻塞主机的执行流程,直到所有数据都被成功加载到 GPU 上,然后才能继续执行后面的代码。如果数据量很大,这个过程可能会非常耗时,严重影响整个程序的性能表现。

而如果将 non_blocking=True 作为 cuda() 函数的参数,数据迁移操作就会变成异步的,即数据开始被复制到 GPU 后,主机不需要等待它们全部被加载到 GPU 上,就可以继续执行其它操作,这样可以充分利用计算资源,减少程序执行时间。

下面是一个简单示例,演示如何在 Tensor 对象上使用 non_blocking=True 参数:

import torch

# 创建 CPU Tensor 对象
x = torch.randn(1000, 1000)

# 将 CPU Tensor 对象移动到 GPU 上
x_gpu = x.cuda(non_blocking=True)

在这个示例中,我们首先创建了一个大小为 1000x1000 的 CPU Tensor 对象 x,然后使用 x.cuda(non_blocking=True) 将它移动到 GPU 上,并启用了异步传输模式。

需要注意的是,在某些情况下,启用 non_blocking=True 可能会导致性能下降或者程序出现错误,特别是在数据量较小或者计算密集型任务中。因此,建议在具体使用时根据实际情况来选择是否启用异步传输模式,避免不必要的性能损失。

另外,如果你使用了异步传输模式,并且需要在 GPU 上执行下一步操作,你可能需要使用 torch.cuda.Stream 类来创建一个新的 CUDA 流(stream),以便在异步操作完成之前等待其它操作的完成。例如:

import torch

# 创建 CPU Tensor 对象
x = torch.randn(1000, 1000)

# 将 CPU Tensor 对象移动到 GPU 上,并启用异步传输模式
x_gpu = x.cuda(non_blocking=True)

# 执行其它操作

# 等待数据异步传输完成
torch.cuda.synchronize()

# 在 CUDA stream 上执行其它操作
with torch.cuda.stream(torch.cuda.Stream()):
    # ...

在这个示例中,我们首先创建了一个大小为 1000x1000 的 CPU Tensor 对象 x,然后使用 x.cuda(non_blocking=True) 将它移动到 GPU 上,并启用了异步传输模式。接着,我们执行了一些其它操作,然后使用 torch.cuda.synchronize() 等待所有异步传输操作完成。最后,我们使用 torch.cuda.Stream 类创建了一个新的 CUDA 流,并在该流上执行了一些其它操作,从而确保这些操作不会与异步传输操作产生竞争关系,保证程序正确性和性能表现。

需要注意的是,如果你使用了异步传输模式,并且没有使用 torch.cuda.synchronize() 函数等待所有异步操作完成,那么在 GPU 上的计算结果可能会出现不正确的情况。因此,在使用异步传输模式时,一定要确保在下一步操作之前,先使用 synchronize() 函数等待数据全部被传输完成。

另外,需要注意的是,在某些情况下,启用 non_blocking=True 也可能会导致程序崩溃或出现错误信息。这可能是由于 CUDA 硬件驱动或 PyTorch 库自身的问题所导致,建议在具体使用时根据实际情况来选择是否启用异步传输模式。

详细介绍以及有错误地方'''Training script. ''' import os from tqdm import tqdm import torch import torch.nn as nn from torch.utils.data import DataLoader from torch.optim import Adam, lr_scheduler from torchsummary import summary from torchvision import transforms import torch.distributed as dist import torch.multiprocessing as mp from models.resnet50 import ResNet50 from runtime_args import args from load_dataset import LoadDataset from plot import plot_loss_acc from helpers import calculate_accuracy device = torch.device("cuda:0" if torch.cuda.is_available() and args.device == 'gpu' else 'cpu') if not os.path.exists(args.graphs_folder) : os.mkdir(args.graphs_folder) model_save_folder = 'resnet_cbam/' if args.use_cbam else 'resnet/' if not os.path.exists(model_save_folder) : os.mkdir(model_save_folder) def train(gpu, args): '''Init models and dataloaders and train/validate model. ''' rank = args.rank * args.gpus + gpu world_size = args.gpus * args.nodes dist.init_process_group(backend='nccl', init_method='env://', world_size=world_size, rank=rank) model = ResNet50(image_depth=args.img_depth, num_classes=args.num_classes, use_cbam=args.use_cbam) torch.cuda.set_device(gpu) model.cuda(gpu) optimizer = Adam(model.parameters(), lr=args.learning_rate) lr_decay = lr_scheduler.ExponentialLR(optimizer, gamma=args.decay_rate) criterion = torch.nn.CrossEntropyLoss().cuda(gpu) summary(model, (3, 224, 224)) model = nn.parallel.DistributedDataParallel(model, device_ids=[gpu]) train_dataset = LoadDataset(dataset_folder_path=args.data_folder, image_size=args.img_size, image_depth=args.img_depth, train=True, transform=transforms.ToTensor()) test_dataset = LoadDataset(dataset_folder_path=args.data_folder, image_size=args.img_size, image_depth=args.img_depth, train=False, transform=transforms.ToTensor()) train_sampler = torch.utils.data.distributed.Distri
03-12
pytorch部分代码如下:train_loss, train_acc = train(model_ft, DEVICE, train_loader, optimizer, epoch,model_ema) for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device, non_blocking=True), Variable(target).to(device,non_blocking=True) # 3、将数据输入mixup_fn生成mixup数据 samples, targets = mixup_fn(data, target) # 4、将上一步生成的数据输入model,输出预测结果,再计算loss output = model(samples) # 5、梯度清零(将loss关于weight的导数变成0) optimizer.zero_grad() # 6、若使用混合精度 if use_amp: with torch.cuda.amp.autocast(): # 开启混合精度 loss = torch.nan_to_num(criterion_train(output, targets)) # 计算loss scaler.scale(loss).backward() # 梯度放大 torch.nn.utils.clip_grad_norm_(model.parameters(), CLIP_GRAD) if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks or global_forward_hooks or global_forward_pre_hooks): return forward_call(*input, **kwargs) class LDAMLoss(nn.Module): def init(self, cls_num_list, max_m=0.5, weight=None, s=30): super(LDAMLoss, self).init() m_list = 1.0 / np.sqrt(np.sqrt(cls_num_list)) m_list = m_list * (max_m / np.max(m_list)) m_list = torch.cuda.FloatTensor(m_list) self.m_list = m_list assert s > 0 self.s = s self.weight = weight def forward(self, x, target): index = torch.zeros_like(x, dtype=torch.uint8) target = torch.clamp(target, 0, index.size(1) - 1) index.scatter(1, target.data.view(-1, 1).type(torch.int64), 1) index_float = index.type(torch.cuda.FloatTensor) batch_m = torch.matmul(self.m_list[None, :], index_float.transpose(0,1)) batch_m = batch_m.view((-1, 1)) x_m = x - batch_m output = torch.where(index, x_m, x) return F.cross_entropy(self.s*output, target, weight=self.weight) 报错:RuntimeError: Expected index [112, 1] to be smaller than self [16, 7] apart from dimension 1 帮我看看如何修改源代码
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值