mkl_malloc 我应该对齐什么值?
What value of alignment should I with mkl_malloc?
函数 mkl_malloc
与 malloc
类似,但有一个额外的 alignment
参数。这是原型:
void* mkl_malloc (size_t alloc_size, int alignment);
我注意到 alignment
的不同值具有不同的性能。除了反复试验之外,是否有 规范的或有记录的 有条不紊的方法来决定 alignment
的最佳值?即正在使用的处理器、正在调用的函数、正在执行的操作等
这个问题广泛适用于任何使用 MKL 的人,所以我很惊讶它没有出现在参考手册中。
更新:我已经尝试过 mkl_sparse_spmm
并且没有注意到将对齐设置为 2 的幂到 1024 字节在性能上的显着差异,之后性能趋于下降。我使用的是 Intel Xeon E5-2683。
唯一的原因,为什么不管你的输入,你没有惩罚/指定对齐方式的好处是,无论你输入什么,你都会得到机器对齐的内存。所以在你的处理器上,它支持 AVX
,无论您的输入如何,您总是获得 32 字节对齐的内存。
您还会看到,无论您选择什么对齐值,内存地址 mkl_malloc
、returns 都是可整除的 32 对齐。或者,您可以测试像 _mm256_load_pd
这样的低级内部函数,这会出现段错误,当使用非 32 字节对齐的地址时,永远不会出现段错误。
一些小细节:OSX 总是给你 32 字节地址,分配内存块时独立于堆/堆栈,而 Linux 总是给你对齐的内存,当分配堆。堆栈在 Linux 上是一个运气问题,但是您已经超出了小矩阵大小的堆栈分配限制。我不了解 Windows 上的内存分配。
我注意到后者,当我为 numerics library 编写测试时,我使用 std::vector<typename T, alignment A>
进行内存分配,而较小的矩阵测试有时会在 Linux 上出现段错误。
TLDR:您的对齐输入已被有效丢弃,无论如何您都会获得机器对齐。
仅当可以使用 SSE/AVX 指令时,对齐才会影响性能 - 这在操作数组时通常是正确的,因为您希望对一系列元素应用相同的操作。
一般来说,你要选择对齐的方式是CPU,如果支持256位寄存器的AVX2,那么你想要32字节对齐,如果支持AVX512,那么64字节是最优的。
为此,mkl_malloc
将保证与您指定的值对齐,但是,显然如果数据是 32 字节对齐的,那么它们也会与 (16, 8, 4.. .)-字节边界。通话的目的是确保始终如此,从而避免任何潜在的并发症。
在我的机器上(Linux 内核 4.17.11 运行 在 i7 6700K 上),mkl_malloc
的默认对齐似乎是 128 字节(对于足够大的数组,如果它们太小了,值似乎是32KB),换句话说,任何小于该值的值都不会影响对齐,但是我可以输入256,数据将对齐到256字节边界。
相比之下,使用 malloc
为 1GB 数据提供 16 字节对齐,为 1KB 提供 32 字节对齐,无论 OS 给我绝对没有关于对齐的偏好。
因此使用 mkl_malloc
很有意义,因为它可以确保您获得所需的对齐方式。但是,这并不意味着您应该将该值设置得过大,这只会导致您浪费内存并可能使您面临更多的缓存未命中。
简而言之,您希望数据与 CPU 中向量寄存器的大小对齐,以便您可以使用相关的扩展。使用 mkl_malloc
和一些对齐参数保证对齐到 至少 该值,但是它可以更多。它应该用于确保数据按照您想要的方式对齐,但绝对没有充分的理由对齐到 1MB。
我认为对齐不能有 "best" 值。根据您的体系结构,对齐通常是由硬件强制执行的 属性,主要是出于优化原因。
关于您的具体问题,重要的是要说明您分配内存的具体目的是什么?哪一块硬件访问内存?例如,我曾使用 DMA 引擎,它要求源地址与每个事务传输大小对齐(其中 xfer 大小 = 4、8、16、32、128)。我还使用了矢量寄存器,其中有一个 128 位对齐的负载是明智的。
总结一下:视情况而定。
函数 mkl_malloc
与 malloc
类似,但有一个额外的 alignment
参数。这是原型:
void* mkl_malloc (size_t alloc_size, int alignment);
我注意到 alignment
的不同值具有不同的性能。除了反复试验之外,是否有 规范的或有记录的 有条不紊的方法来决定 alignment
的最佳值?即正在使用的处理器、正在调用的函数、正在执行的操作等
这个问题广泛适用于任何使用 MKL 的人,所以我很惊讶它没有出现在参考手册中。
更新:我已经尝试过 mkl_sparse_spmm
并且没有注意到将对齐设置为 2 的幂到 1024 字节在性能上的显着差异,之后性能趋于下降。我使用的是 Intel Xeon E5-2683。
唯一的原因,为什么不管你的输入,你没有惩罚/指定对齐方式的好处是,无论你输入什么,你都会得到机器对齐的内存。所以在你的处理器上,它支持 AVX
,无论您的输入如何,您总是获得 32 字节对齐的内存。
您还会看到,无论您选择什么对齐值,内存地址 mkl_malloc
、returns 都是可整除的 32 对齐。或者,您可以测试像 _mm256_load_pd
这样的低级内部函数,这会出现段错误,当使用非 32 字节对齐的地址时,永远不会出现段错误。
一些小细节:OSX 总是给你 32 字节地址,分配内存块时独立于堆/堆栈,而 Linux 总是给你对齐的内存,当分配堆。堆栈在 Linux 上是一个运气问题,但是您已经超出了小矩阵大小的堆栈分配限制。我不了解 Windows 上的内存分配。
我注意到后者,当我为 numerics library 编写测试时,我使用 std::vector<typename T, alignment A>
进行内存分配,而较小的矩阵测试有时会在 Linux 上出现段错误。
TLDR:您的对齐输入已被有效丢弃,无论如何您都会获得机器对齐。
仅当可以使用 SSE/AVX 指令时,对齐才会影响性能 - 这在操作数组时通常是正确的,因为您希望对一系列元素应用相同的操作。
一般来说,你要选择对齐的方式是CPU,如果支持256位寄存器的AVX2,那么你想要32字节对齐,如果支持AVX512,那么64字节是最优的。
为此,mkl_malloc
将保证与您指定的值对齐,但是,显然如果数据是 32 字节对齐的,那么它们也会与 (16, 8, 4.. .)-字节边界。通话的目的是确保始终如此,从而避免任何潜在的并发症。
在我的机器上(Linux 内核 4.17.11 运行 在 i7 6700K 上),mkl_malloc
的默认对齐似乎是 128 字节(对于足够大的数组,如果它们太小了,值似乎是32KB),换句话说,任何小于该值的值都不会影响对齐,但是我可以输入256,数据将对齐到256字节边界。
相比之下,使用 malloc
为 1GB 数据提供 16 字节对齐,为 1KB 提供 32 字节对齐,无论 OS 给我绝对没有关于对齐的偏好。
因此使用 mkl_malloc
很有意义,因为它可以确保您获得所需的对齐方式。但是,这并不意味着您应该将该值设置得过大,这只会导致您浪费内存并可能使您面临更多的缓存未命中。
简而言之,您希望数据与 CPU 中向量寄存器的大小对齐,以便您可以使用相关的扩展。使用 mkl_malloc
和一些对齐参数保证对齐到 至少 该值,但是它可以更多。它应该用于确保数据按照您想要的方式对齐,但绝对没有充分的理由对齐到 1MB。
我认为对齐不能有 "best" 值。根据您的体系结构,对齐通常是由硬件强制执行的 属性,主要是出于优化原因。
关于您的具体问题,重要的是要说明您分配内存的具体目的是什么?哪一块硬件访问内存?例如,我曾使用 DMA 引擎,它要求源地址与每个事务传输大小对齐(其中 xfer 大小 = 4、8、16、32、128)。我还使用了矢量寄存器,其中有一个 128 位对齐的负载是明智的。
总结一下:视情况而定。