Memory Format(Channel First 和 Channel Last )

本文介绍了内存格式在计算机内存中存储数据的方式,及其在数据读写效率,特别是深度学习中的重要性。重点讨论了行优先、列优先和ChannelFirst/ChannelLast的区别,以及它们在PyTorch和TensorFlow中的应用,强调了合理选择内存格式以优化性能的重要性。
摘要由CSDN通过智能技术生成

Memory Format

基本概念

Memory Format,也称作数据布局,是指在计算机内存中存储数据的方式。它对数据的读取和写入效率有重大影响,特别是在处理大规模数据,如在机器学习和深度学习的矩阵运算中。

原理

内存格式包括多种方式,根据数据在内存中的排列序列来分类,比如行优先(Row-major)和列优先(Column-major):

  • 行优先布局:数组的连续元素是一行中的元素,这种方式是C语言和Python的NumPy库使用的方式。
  • 列优先布局:数组的连续元素是一列中的元素,Fortran使用这种布局。

不同的存储格式影响缓存的效率。计算机的缓存是为了减少处理器和内存间数据交换的等待时间,是一种快速的存储器。如果数据是连续存储的,那么处理器从内存中读取数据时能够更高效地利用缓存。

Channel First 和 Channel Last 的含义

Channel First
Channel First 指的是图片数据的通道(Channel)维度排在第一位(排在批量大小之后),即数据格式为 (批量大小, 通道数, 高度, 宽度)。在例如PyTorch这样的深度学习框架中,默认使用的就是 Channel First 格式。
例如,一个含有3个彩色图像(RGB,即3个通道)的批量,每个图像的尺寸为64x64像素,则这个批量的数据形状将会是(3, 3, 64, 64)。

Channel Last
Channel Last 即图片数据的通道(Channel)维度排在最后,即数据格式为 (批量大小, 高度, 宽度, 通道数)。在TensorFlow中,特别是其Keras高级API,默认使用 Channel Last 数据格式。
用之前的例子,同样的批量数据在 Channel Last 格式下将会是(3, 64, 64, 3)。

用法区别
在编写代码处理图像数据的时候,应当留意框架对于通道的处理顺序,并确保数据输入匹配。
在PyTorch中使用Channel First:

import torch
# 创建一个Channel First的Tensor
tensor_cf = torch.randn(3, 3, 64, 64)
在TensorFlow/Keras中使用Channel Last:
import tensorflow as tf
# 创建一个Channel Last的Tensor
tensor_cl = tf.random.normal((3, 64, 64, 3))

Channel First:

  • 优势:在一些深度学习库中,如PyTorch,Channel First 可以更好地与底层的Cuda库集成,从而可能提供更好的性能。
  • 劣势:不如Channel Last直观,因为在自然图像中,通道总是跟随每个像素,而非前置。

Channel Last:

  • 优势:更符合图像处理的直观理解,因为颜色通道直接附着在每个像素点后。很多图像处理库(比如OpenCV)也是采用这种格式,因此在用TensorFlow/Keras进行编程

Conv2d中存Memory Format的传递

在channels first上面直接优化Conv,无法达到最佳性能(那种可以退化成gemm的除外),主要原因是C上的访存不连续,而一般情况下我们需要在C上做vectorization。
所以在channels first上面,input和weight首先需要转化成对CPU性能友好的blocked format (例如nChw16c, OIhw16i16o),这个过程称为"reorder";再送给onednn的primitive计算;
最后output还需要从blocked format转换回NCHW。这些reorder对整体性能来说是个累赘,占用了宝贵的memory带宽。

PyTorch CPU上Conv2d memory format的传递方式:

在这里插入图片描述
一般来说,CL的性能要优于CF,因为可以省掉activation的reorder,这也是当初去优化channels last的最大动因。

另外,PyTorch上面的默认格式是CF的,对于特定OP来说,如果没有显示的CL支持,NHWC的input会被当作non-contiguous的NCHW来处理,从而output也是NCHW的,这带来的一个问题就是整个memory format传递的链条会被打断。也就是一开始虽然有做了to channels last的操作,但是跑着跑着就变回NCHW了。

使用方法

理解了内存格式的原理后,可以根据具体应用来优化内存布局。在深度学习框架中,如PyTorch,可以使用不同的Memory Format进行张量(Tensor)的操作优化。
在PyTorch中使用内存格式的例子:

import torch

# 默认的内存格式是行优先
tensor = torch.randn(10, 20)

# 转换为列优先格式
tensor_column_major = tensor.t().contiguous()

# 采用特殊的内存格式,如Channels Last,用于优化计算机视觉模型的性能
tensor_channels_last = tensor.to(memory_format=torch.channels_last)

总结

在实际应用中,正确地选择和使用内存格式对程序的性能有着不容忽视的影响。大多数情况下,默认的行优先格式已足够,但在特定场景下,例如深度学习的卷积神经网络中处理大量图像数据,合理应用列优先或特定的内存格式如Channels Last,能够显著优化计算性能。因此,理解并合理使用内存格式,可以提高数据处理的效率和速度。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值