乐于分享
好东西不私藏

近期人肉学PyTorch源码的人肉总结(2)

近期人肉学PyTorch源码的人肉总结(2)

PyTorch是什么?

PyTorch 是一种用于构建深度学习模型的功能完备框架,是一种通常用于图像识别和语言处理等应用程序的机器学习。使用 Python 编写,因此对于大多数机器学习开发者而言,学习和使用起来相对简单。PyTorch 的独特之处在于,它完全支持 GPU,并且使用反向模式自动微分技术,因此可以动态修改计算图形。这使其成为快速实验和原型设计的常用选择。

https://www.nvidia.cn/glossary/pytorch/
Matt White在PyTorch Day India 2026的Keynote Speech上说,PyTorch已经成为人工智能领域训练以及推理生态的核心[1]。
[1] Matt White PyTorch Day India 2026 Keynote Speech https://www.youtube.com/watch?v=ou_CYZrfIVA&t=324s
还是从小例程出发
      1 import torch      2 import torch.nn as nn      3 import torch.optim as optim      4       5 # ----------------------------      6 # 1. Create training data      7 # ----------------------------      8 # Input: [x, y]      9 # Target: z = x^2 + y^3     10 torch.manual_seed(0)     11      12 X = torch.randn(100002)              # 1000 samples, (x, y)     13 y = X[:, 0]**2 + X[:, 1]**3           # true function

在以上的PyTorch例程中,第 10 行通过 torch.manual_seed(0) 设置随机种子为 0,以确保生成的随机数可复现;

第 12 行用 torch.randn(10000, 2) 生成一个 10000×2 的张量 X,每行是一个样本的输入特征 (x, y),元素服从标准正态分布;

第 13 行通过 y = X[:, 0]**2 + X[:, 1]**3 计算每个样本的目标值 z,即第一个特征平方加上第二个特征立方,从而得到训练数据的输入 X 和输出 y,为后续模型训练提供基础。

继续跟踪第13行张量乘法的C++实现

1.  把断点设置在pytorch/aten/src/ATen/native/cpu/PowKernel.cpp

67行是Y的3次幂实现的地方

2. 用gdb跟到断点后,回溯到第51层调用栈

(gdb) f 51

#51 0x0000555555812674 in _PyEval_Vector (tstate=0x555555bd5cc0 <_PyRuntime+299040>, func=0x7fffd4847050, locals=0x0, args=0x7fffffffb550, argcount=2, 

    kwnames=0x0) at ../Python/ceval.c:1814

1814    return _PyEval_EvalFrame(tstate, frame, 0);

(gdb) p frame

$4 = (_PyInterpreterFrame *) 0x7ffff7e49088

(gdb) p func

$5 = (PyFunctionObject *) 0x7fffd4847050

这里的func是第55层调用栈,通过名字查找得来的指针:

2612 static PyObject *

2613 vectorcall_maybe(PyThreadState *tstate, PyObject *name,

2614                 PyObject *const *args, Py_ssize_t nargs)

2615 {

2616    assert(nargs >= 1);

2617

2618    int unbound;

2619    PyObject *self = args[0];

2620    PyObject *func = lookup_maybe_method(self, name, &unbound);

2621    if (func == NULL) {

2622        if (!PyErr_Occurred())

2623            Py_RETURN_NOTIMPLEMENTED;

2624        return NULL;

2625    }

2626    PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs);

2627    Py_DECREF(func);

2628    return retval;

2629 }

第2620行从字典中查找”__pow__”对应的函数,而加入字典的时机是对__tensor.py的1107行的解释执行:

第51层调用栈取出与func指针对应的字节码序列(存放在frame的结构中,然后解释执行)

3. 跟踪第51层调用栈的字节码执行过程

使用gdb跟踪第51层调用栈的字节码执行过程,我跟到了最后存放C++函数指针的地方:

4. 通过gdb跟踪这个MAKE_CELL字节码的产生过程

我跟到了对函数

_handle_torch_function_and_wrap_type_error_to_not_implemented的编译:

最后用大白话总结一下

_tensor.py文件中:

1107     __pow__ = cast(1108         Callable[1109             ["torch._C.TensorBase"Union["Tensor"intfloatboolcomplex]],1110             "Tensor",1111         ],1112         _handle_torch_function_and_wrap_type_error_to_not_implemented(1113             _C.TensorBase.pow1114        ),1115      )

 1113行把_C.TensorBase.pow传给函数

_handle_torch_function_and_wrap_type_error_to_not_implemented

最后执行的时候,执行的是存放在_handle_torch_function_and_wrap_type_error_to_not_implemented函数里的CELL的函数指针

另外,今天听黄仁勋两天前斯坦福访谈[1] 第31分29秒: “英伟达的软件工程师比以前更忙了。 因为过去,他们有一个想法,他们必须手写代码。 现在,如果有一个想法,写代码基本不花时间。所以,现在是全公司都在等你的下一个想法“。 

Now we have an idea, it takes no time to code, now the whole company is waiting for your next idea.

https://www.youtube.com/watch?v=tofBqR5N1RI

”计“山有路勤为径,”算“海无涯苦作舟