我是使用 SSE/SSE2 指令优化代码的新手,到目前为止我还没有走得太远。据我所知,常见的 SSE 优化函数如下所示:
void sse_func(const float* const ptr, int len){
if( ptr is aligned )
{
for( ... ){
// unroll loop by 4 or 2 elements
}
for( ....){
// handle the rest
// (non-optimized code)
}
} else {
for( ....){
// regular C code to handle non-aligned memory
}
}
}
但是,如何正确判断内存是否ptr
指向的位置通过例如对齐16字节?我认为我必须包含非对齐内存的常规 C 代码路径,因为我无法确保传递给此函数的每个内存都会对齐。使用内在函数将数据从未对齐的内存加载到 SSE 寄存器似乎非常慢(甚至比常规 C 代码慢)。
先感谢您...
#define is_aligned(POINTER, BYTE_COUNT) \
(((uintptr_t)(const void *)(POINTER)) % (BYTE_COUNT) == 0)
演员阵容void *
(或同等学历,char *
)是必要的,因为该标准仅保证可逆转换为uintptr_t
for void *
.
如果您想要类型安全,请考虑使用内联函数:
static inline _Bool is_aligned(const void *restrict pointer, size_t byte_count)
{ return (uintptr_t)pointer % byte_count == 0; }
并希望编译器优化如果byte_count
是一个编译时常数。
为什么我们需要转换为 void *
?
C 语言允许不同的指针类型有不同的表示,例如你可以有一个 64 位的void *
类型(整个地址空间)和 32 位foo *
类型(一段)。
转换foo *
-> void *
可能涉及实际计算,例如添加偏移量。该标准还将(任意)指针转换为整数时发生的情况留给实现,但我怀疑它通常被实现为 noop。
对于这样的实现,foo *
-> uintptr_t
-> foo *
会起作用,但是foo *
-> uintptr_t
-> void *
and void *
-> uintptr_t
-> foo *
不会。对齐计算也不会可靠地工作,因为您只检查相对于段偏移的对齐,这可能是也可能不是您想要的。
结论:始终使用void *
获得与实现无关的行为。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)