与numpy中的内存对齐有关的三个用例(自1.14开始):
创建字段对齐方式类似于C结构的结构化数据类型。
通过使用uint分配而不是memcpy来加快复制操作
确保对ufuncs / setitem / casting代码的安全对齐访问
Numpy使用两种不同的对齐方式来实现这些目标:“正确对齐”和“ Uint对齐”。
“ True”对齐是指C中等效C类型的依赖于体系结构的对齐。例如,在x64系统numpy.float64
中,等同double
于C。在大多数系统上,它具有4或8个字节的对齐(并且可以是在gcc中由选项
malign-double
)控制。如果变量的内存偏移量是其对齐方式的倍数,则该变量在内存中对齐。在某些系统上(例如sparc),需要进行内存对齐,而在其他系统上,则可以提高速度。
“ Uint”对齐方式取决于数据类型的大小。它被定义为numpy的复制代码用于复制数据类型的uint的“真正对齐”,如果没有等效的uint,则为undefined / unaligned。当前numpy使用uint8,uint16,uint32,uint64和uint64分别复制大小为1,2,4,8,16字节的数据,并且所有其他大小的数据类型都不能uint对齐。
例如,在(典型的Linux x64 gcc)系统上,numpy complex64
数据类型实现为。它的“真”对齐为4,“ uint”的对齐为8(等于的真正对齐
)。struct { float real, imag; }
uint64
拱型true-aln uint-aln — — — ——– ——– x86_64 complex64 4 8 x86_64 float128 16 8 x86 float96 4-
align
numpy中使用的单词有4种相关用法:
的
dtype.alignment
(属性descr->alignment
中C)。这是为了反映类型的“真实对齐”。除align=True
以下所述创建的结构化类型外,所有数据类型都有与拱有关的默认值。
ALIGNED
ndarray 的标志,由计算IsAligned
并由检查PyArray_ISALIGNED
。这是根据计算的dtype.alignment
。设置为True
数组中的每个项目是否都位于与一致的内存位置dtype.alignment
,如果数据ptr和数组的所有跨度是该对齐的倍数,则为这种情况。
align
dtype构造函数的关键字,仅影响结构化数组。如果未手动提供结构的字段偏移量,则numpy会自动确定偏移量。在这种情况下,请align=True
填充结构,以使每个字段在内存中都是“ true”对齐方式,并设置dtype.alignment
为最大的字段“ true”对齐方式。这就像C结构通常所做的那样。否则,如果手动提供了偏移量或项目大小,则align=True
只需检查所有字段是否为“ true”对齐,并且总项目大小为最大字段对齐的倍数即可。无论哪种情况dtype.isalignedstruct
,也都设置为True。
IsUintAligned
用于确定ndarray是否“ uint对齐”,类似于IsAligned
检查真对齐的方式。
以下是上述变量的使用方式:
创建对齐的结构:为了了解如何在时偏移字段
align=True
,numpy查找field.dtype.alignment
。这包括嵌套结构化数组的字段。Ufuncs:如果
ALIGNED
数组的标志为False,则ufuncs将在评估之前缓冲/广播该数组。这是必需的,因为ufunc内部循环直接访问原始元素,如果元素未真正对齐,则在某些拱形上可能会失败。Getitem / setitem / copyswap函数:与ufuncs相似,这些函数通常具有两个代码路径。如果
ALIGNED
为False,则它们将使用一个缓冲参数的代码路径,以使它们为真对齐。交错的复制代码:在这里,使用“统一对齐”。如果数组的项目大小等于1、2、4、8或16个字节,并且数组是uint对齐的,则numpy将对适当的N执行操作。否则,将执行numpy个副本。
*(uintN*)dst) = *(uintN*)src)
memcpy(dst, src, N)
Nditer代码:由于这通常称为大步复制代码,因此必须检查“ uint对齐”。
强制转换代码:这将检查是否为“ true”对齐方式,如果对齐则也是 如此。否则,它将 在dstval / srcval对齐的地方进行。
*dst = CASTFUNC(*src)
memmove(srcval, src); dstval = CASTFUNC(srcval); memmove(dst, dstval)
请注意,strided-copy和strided-cast代码是紧密交织的,因此,即使复制代码仅需要uint对齐,而强制转换代码仅是真正对齐,它们所处理的任何数组也必须均为uint和true对齐。如果需要大量重写此代码,最好允许他们使用不同的对齐方式。