type
status
date
slug
summary
tags
category
icon
password
Property
Sep 14, 2024 09:22 AM
而我们 面朝大海看潮涨了潮又落
起
2023悄无声息地快溜走一个月了,旧岁也在爆竹声中被赶走了,那就让自己努力写点什么吧。
关于学习
感觉没什么有意思的可以拿出来写写,拿最近看到的数组中的stride来水一下吧(
存储一个多维矩阵时,内存中实际存储的是一个一维数组,在二维的情况下,熟知的有行主序,列主序的方式,stride就是不同于这两类的一个存储方式。
stride存储的映射方式为
A[i, j] => Adata[i * A.strides[0] + j * A.strides[1]]
以2x3的矩阵为例,stride为[3,1]时就等同于行主序,为[1,2]时就等同于列主序,当然stride的映射方式可以推广到更高维度。
而为什么要有stride这种存储方式呢?
有以下几点好处;
- 做转置时,也只需要交换stride就可以
- 做广播操作时,只需要插入一个值为0的stride
- 做数组切片时,只需要修改初始偏移量和形状就可以,不需要拷贝底层数据
接下来对其一一解释一下:
首先,考虑对一个矩阵,如何求出对应的stride?
在dlsys hw3中可以看到一段代码
def compact_strides(shape): """ Utility function to compute compact strides """ stride = 1 res = [] for i in range(1, len(shape) + 1): res.append(stride) stride *= shape[-i] return tuple(res[::-1])
如何理解呢?举一个具体的例子一个shape为(4,3,2)的矩阵,把它看作4个3*2的小矩阵放在一起,那么第0维每跨一步就是3*2=6,第1维跨一步就是2,最后一维跨一步就是1,stride即(6,2,1)
所以stride其实就是每一维跨的步长。
在明白stride的本质后再看这三个问题:
- 做转置时,也只需要交换stride就可以
- 做广播操作时,只需要插入一个值为0的stride
例如如果要把2×3的张量广播到2×3×4,在变换shape以后只需要把strides置为(3, 1, 0),对照上文映射关系式,即
A[i, j] => Adata[i * 2 + j * 3 + k * 0]
0不会影响在内存一维数组中索引到的值,但k为4,相当于循环索引了4次,达到广播的效果
- 做数组切片时,只需要修改初始偏移量和形状就可以,不需要拷贝底层数据
通过给定每一维的start,end,step,即每一维的起始位置,结束位置,子步长,即可计算出对应切分的子矩阵的strides以及shape,offset,从而得到子矩阵。
相关资料
关于动漫
最近把春物补完了,看着大老师的一步步变成现充的样子,我还是更喜欢他前面桀骜不驯说圣经的调调(误
关于阅读
最近看了《麦田里的守望者》,还没看完,emm,没怎么看懂,感觉行文挺琐碎的,没看出什么内涵,大概我没有那种时代背景带来的感受吧。
另外,机缘巧合下看了看余华的《第七天》,果然,挺惨的,这下不止活着惨,死了也挺惨的,不过今早我忽然想到,从旁观者的角度看主人公的生活确实尽是悲惨之事,但代入主人公视角进去,好像又能从悲惨的故事中发现些幸福的片段?至于作者到底想表达什么,我这个没有文学性的脑袋大抵是读不懂了,就当睡前读物吧。
终
不知不觉又虚度了人生的几个小时,那就,下次见吧,ma ta ne(またね)~
- 作者:Difer
- 链接:https://difer.cn/article/e944fe6b-0340-46cb-9cfd-2f31eab5553e
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。