Python打卡第34天

@浙大疏锦行

作业:

loss.item() 虽然只在 CPU 中执行,但它会触发一次 GPU → CPU 的强制同步,这是影响性能的关键!

loss.item() 做了什么?

  1. 数据原本在 GPU 上
  • 训练时,loss 是一个 GPU 上的张量(比如 torch.cuda.FloatTensor)。

  • GPU 可以高效计算,但 不能直接读取数值(就像工厂生产产品,但你要亲自去工厂拿货)。

  1. .item() 的本质
  • loss.item() 做了 3 件事:

    1. 暂停 GPU 计算:强制 GPU 停下当前所有任务(同步点)。

    2. 把数据从 GPU 复制到 CPU(通过 PCIe 总线,就像用卡车从工厂运货到商店)。

    3. 转换成 Python 数字(floatint),因为 Python 只能处理 CPU 数据。

  1. 为什么这么慢?
  • 不是 .item() 本身慢,而是 GPU→CPU 的传输和同步慢!

  • 每次调用 .item(),GPU 都要:

    • 等所有并行计算完成(比如 1000 个 CUDA 核心都要停)。

    • 走 PCIe 总线(带宽有限,延迟高)。

    • 等 CPU 确认收到数据后才能继续计算。

__call__方法

在 Python 中,call 方法是一个特殊的魔术方法(双下划线方法),它允许类的实例像函数一样被调用。这种特性使得对象可以表现得像函数,同时保留对象的内部状态。

比如:

python 复制代码
# 不带参数的call方法
class Counter:
    def __init__(self):
        self.count = 0
    
    def __call__(self):
        self.count += 1
        return self.count

# 使用示例
counter = Counter()
print(counter())  # 输出: 1
print(counter())  # 输出: 2
print(counter())  # 输出: 3
print(counter.count)  # 输出: 3
python 复制代码
1
2
3
3
python 复制代码
# 带参数的call方法
class Adder:
    def __call__(self, a, b):
        print("唱跳篮球rap")
        return a + b

adder = Adder()
print(adder(3, 5))  # 输出: 8
python 复制代码
唱跳篮球rap
8

为什么 PyTorch 要用 __call__ 而不是直接暴露 forward

  1. 封装性:__call__ 可以统一管理 forward 前后的逻辑(如自动梯度、Hook 机制)。

  2. 安全性:防止用户直接调用 forward 导致梯度丢失或计算图断裂。

  3. 一致性:让所有模块(nn.Linearnn.Conv2d、自定义模型)都能用 module(x) 的方式调用。

相关推荐
TOPGUS几秒前
谷歌SEO第三季度点击率趋势:榜首统治力的衰退与流量的去中心化趋势
大数据·人工智能·搜索引擎·去中心化·区块链·seo·数字营销
松☆13 分钟前
CANN深度解析:构建高效AI推理引擎的软件基
人工智能
YongCheng_Liang15 分钟前
从零开始学 Python:自动化 / 运维开发实战(核心库 + 3 大实战场景)
python·自动化·运维开发
ujainu16 分钟前
CANN仓库中的AIGC可持续演进工程:昇腾AI软件栈如何构建“活”的开源生态
人工智能·开源·aigc
鸽芷咕26 分钟前
为什么越来越多开发者转向 CANN 仓库中的 Python 自动化方案?
python·microsoft·自动化·cann
秋邱27 分钟前
用 Python 写出 C++ 的性能?用CANN中PyPTO 算子开发硬核上手指南
开发语言·c++·python
光锥智能27 分钟前
从连接机器到激活知识:探寻工业互联网深水区的山钢范式
人工智能
GHL28427109030 分钟前
分析式AI学习
人工智能·学习·ai编程
ujainu1 小时前
CANN仓库中的AIGC性能极限挑战:昇腾软件栈如何榨干每一瓦算力
人工智能·开源
wenzhangli71 小时前
ooderA2UI BridgeCode 深度解析:从设计原理到 Trae Solo Skill 实践
java·开发语言·人工智能·开源