pytorch中深度拷贝_PyTorch为何如此高效好用?来探寻深度学习框架的内部架构

本文深入探讨了 PyTorch 框架的内部架构,揭示了其高效性能的原因。PyTorch 的核心优势在于其 C/C++ 实现,利用 Python 扩展进行底层操作,如 Zero-copy 技术实现 PyTorch 张量与 Numpy 数组之间的无缝转换。此外,文章还介绍了张量存储、共享内存和 DLPack 标准,这些特性使得 PyTorch 在多进程共享和跨框架数据交换中表现出色。
摘要由CSDN通过智能技术生成

作为 Facebook 人工智能团队(FAIR)提供支持的深度学习框架,PyTorch 自 2017 年 1 月推出以来立即成为了一种流行开发工具。其在调试、编译等方面的优势使其受到了学界研究者们的普遍欢迎。本文中,来自蒙特利尔综合理工学院的研究员 Christian S. Perone 将为我们介绍这种神经网络框架的内部架构,揭开 PyTorch 方便好用的真正原因。

前言

本文主要介绍了 PyTorch 代码库,旨在为 PyTorch 及其内部架构设计提供指导,核心目标是为那些想了解 API 知识之外的人提供有益的帮助,并给出之前教程所没有的新内容。注意:PyTorch 构建系统需要大量使用代码设置,因此其他人的描述我将不再重复。如果你感兴趣,请参考原文提供的扩展资料。

C/C++中 Python 扩展对象的简介

你可能知道可以借助 C/C++扩展 Python,并开发所谓的「扩展」。PyTorch 的所有繁重工作由 C/C++实现,而不是纯 Python。为了定义 C/C++中一个新的 Python 对象类型,你需要定义如下实例的一个类似结构:// Python object that backs torch.autograd.Variable

struct THPVariable {

PyObject_HEAD

torch::autograd::Variable cdata;

PyObject* backward_hooks;

};

如上,在定义的开始有一个称之为 PyObject_HEAD 的宏,其目标是标准化 Python 对象,并扩展至另一个结构,该结构包含一个指向类型对象的指针,以及一个带有引用计数的字段。

Python API 中有两个额外的宏,分别称为 Py_INCREF() 和 Py_DECREF(),可用于增加和减少 Python 对象的引用计数。多实体可以借用或拥有其他对象的引用(因此引用计数被增加),而只有当引用计数达到零,Python 才会自动删除那个对象的内存。想了解更多有关 Python C/++扩展的知识,请参见:https://docs.python.org/3/extending/newtypes.html。

有趣的事实:使用小的整数作为索引、计数等在很多应用中非常见。为了提高效率,官方 CPython 解释器缓存从-5 到 256 的整数。正由于此,声明 a = 200; b = 200; a is b 为真,而声明 a = 300; b = 300; a is b 为假。

Zero-copy PyTorch 张量到 Numpy,反之亦然

PyTorch 有专属的张量表征,分离 PyTorch 的内部表征和外部表征。但是,由于 Numpy 数组的使用非常普遍,尤其是当数据加载源不同时,我们确实需要在 Numpy 和 PyTorch 张量之间做转换。正由于此,PyTorch 给出了两个方法(from_numpy() 和 numpy()),从而把 Numpy 数组转化为 PyTorch 数组,反之亦然。如果我们查看把 Numpy 数组转化为 PyTorch 张量的调用代码,就可以获得有关 PyTorch 内部表征的更多洞见:at::Tensor tensor_from_numpy(PyObject* obj) {

if (!PyArray_Check(obj)) {

throw TypeError("expected np.ndarray (got %s)", Py_TYPE(obj)->tp_name);

}

auto array = (PyArrayObject*)obj;

int ndim = PyArray_NDIM(array);

auto sizes = to_aten_shape(ndim, PyArray_DIMS(array));

auto strides = to_aten_shape(ndim, PyArray_STRIDES(array));

// NumPy strides use bytes. Torch strides use element counts.

auto element_size_in_bytes = PyArray_ITEMSIZE(array);

for (auto& stride : strides) {

stride /= element_size_in_bytes;

}

// (...) -

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值