1. 原因原理
编程中的类型对齐问题主要是处于性能考虑,如果不做对齐,那么单个数据元素的访问很容易跨在多个时钟周期上,从而导致性能下降。
内建数据类型的对齐,是由编译器和C语言库的API实现中自动完成的,这对于用户是透明的,比如常用的 malloc。
有时候需要使用大块数据,同时需要提高性能,可能需要 64 bytes对齐,按照机器的cache line对齐等,这时候可以使用 posix_memalign:
Function: int posix_memalign (void **memptr, size_t alignment, size_t size)
Preliminary: | MT-Safe | AS-Unsafe lock | AC-Unsafe lock fd mem | See POSIX Safety Concepts.
The posix_memalign
function is similar to the memalign
function in that it returns a buffer of size bytes aligned to a multiple of alignment. But it adds one requirement to the parameter alignment: the value must be a power of two multiple of sizeof (void *)
.
If the function succeeds in allocation memory a pointer to the allocated memory is returned in *memptr
and the return value is zero. Otherwise the function returns an error value indicating the problem. The possible error values returned are:
ENOMEM
There was insufficient memory available to satisfy the request.
EINVAL
alignment is not a power of two multiple of sizeof (void *)
.
This function was introduced in POSIX 1003.1d. Although this function is superseded by aligned_alloc
, it is more portable to older POSIX systems that do not support ISO C11.
更多内存对齐的API的内容可参考:
Aligned Memory Blocks (The GNU C Library)
2. 测试代码
#include <stdlib.h>
#include <stdio.h>
int main()
{
// posix_memalign, (, void **, p,. size_t, alignment,. size_t, size. )
float* p = nullptr;
int res;
for(int i=0; i<10; i++)
{
res = 99;
res = posix_memalign((void**)&p, 64, 100*sizeof(float));
p[99] = 0.333f + i;
printf("res=%d, p[99] = %7.4f , p = %p\n", res, p[99], p);
// free(p);
}
for(int i=0; i<10; i++)
{
p = (float*)malloc(100*sizeof(float));
p[99] = 10.333f + i;
printf("res=%d, p[99] = %7.4f , p = %p\n", p[99], p);
// free(p);
}
return 0;
}
Makefile:
EXE := hello_posix_memalign
$(EXE):
.PHONY: clean
clean:
-rm -rf $(EXE)