SIMD相关学习

C语言字节对齐
CPU访问内存
在这里插入图片描述

为什么要内存对齐?
直观地看:CPU一次只能读取出4n,4n+1,4n+2,4n+3的信息
如果把一个short类型变量(占两个字节)存在如图红色位置,那么我就要读两次
在这里插入图片描述
“如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char”我不明白,这三次的地址分别是多少,如何计算确定的?
我的理解如上图所示。(CPU读取内存是按字节、字、双字来的)

#include <stdio.h>
main()
{
struct A {
    int a;
    char b;
    short c;
};
 
struct B {
    char b;
    int a;
    short c;
};
 
#pragma pack (2) /*指定按2字节对齐*/
struct C {
    char b;
    int a;
    short c;
};
#pragma pack () /*取消指定对齐,恢复缺省对齐*/
 
 
 
#pragma pack (1) /*指定按1字节对齐*/
struct D {
    char b;
    int a;
    short c;
};
#pragma pack ()/*取消指定对齐,恢复缺省对齐*/
 
int s1=sizeof(struct A);
int s2=sizeof(struct B);
int s3=sizeof(struct C);
int s4=sizeof(struct D);
printf("%d\n",s1); //8
printf("%d\n",s2); //12
printf("%d\n",s3); //8
printf("%d\n",s4); //7
}

有三个概念:自然对齐值 指定对齐值 有效对齐值
自然对齐值:
char int short的自然对齐值是1,4,2
结构体的自然对齐值是成员中最大的对齐方式
要求:地址%自然对齐=0
指定对齐值:
可以用__attribute__修改或者pragma pack (n)
有效对齐值:指定对齐值与自身对齐值中较小者,实际中用的

假设结构体从地址空间0x0000开始放,每个变量都要满足有效对齐值

无指定情况下:char int short的有效对齐值是1,4,2,结构体是4

struct A {
    int a;
    char b;
    short c;
}

a:0-4 0%4=0
b:4-5 4%1=0
c:6-8 5%2!=0 因此填充一格,跳到6
最后发现消耗4+1+1+2=8,满足结构体的自然对齐值4,最终是8

无指定情况下:char int short的有效对齐值是1,4,2,结构体是4

struct B {
    char b;
    int a;
    short c;
};

b: 0-1 0%1=0
a: 4-8 1%4!=0 填充三格
c: 8-10 8%2=0
最后发现消耗10,不满足结构体的自然对齐值4,填补两个,最终是12

有效对齐值是2

#pragma pack (2) /*指定按2字节对齐*/
struct C {
    char b;
    int a;
    short c;
};
#pragma pack () /*取消指定对齐,恢复缺省对齐*/

b: 0-1 0%2=0
a: 2-6 1%2!=0,填充1个
c: 6-8 6%2=0
最后消耗8个,满足结构体的有效对齐值2,最终是8

有效对齐值是1

#pragma pack (1) /*指定按1字节对齐*/
struct D {
    char b;
    int a;
    short c;
};
#pragma pack ()/*取消指定对齐,恢复缺省对齐*/

b: 0-1 0%1=0
a: 1-5 1%1=0
c: 5-7 5%1=0
最后消耗7个,满足结构体的有效对齐值1,最终是7

最后从评论区补充:
32bit机子这是按照4字节对齐的,64bit机子是按照8字节对齐的,最终对齐字节是CPU、编译器和有效对齐字节中最小的值
#pragma pack(n)和__attribute__((aligned(m)))的区别

在这里插入图片描述
应该如xiaoxiaosunzhao所说

我们避免数据不对齐主要为了避免cross cache line,page boundary 和 cache bank conflic,不同的cpu有着不同的着重点。

VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。 (Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果

SSE指令集入门
在C/C++代码中使用SSE等指令集的指令(3)SSE指令集基础
在C/C++代码中使用SSE等指令集的指令(4)SSE指令集Intrinsic函数使用
Streaming SIMD Extensions
总的来说,当循环没有if else分支的时候,可以使用该方法,批量计算。
在这里插入图片描述

源码不太了解的地方:
uint8_t * bf_base; //bloom filter base, 32 bytes aligned
uint8_t * bf_base_rec; // the real memory space of bloom filter
memset(bf_base_rec, 0, m/8 + 32); ? +32是干嘛的?

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值