data structure alignment(数据对齐)

概述:

数据对齐指数据在计算机内存中排放和获取的方式。包含三个方面:数据对齐(data alignment)、数据结构填充(data alignment)、打包(packing)

如果数据是自然对齐的话,CPU读写会更高效。自然对齐指数据地址是数据大小的倍数。为保证自然对齐,可能会在结构的开头或结尾进行一些填充

定义:

内存地址对齐:一个内存地址a被称为n-byte对齐,如果a是n的倍数,其中n是2的幂。因此n对齐的地址的低log2(n)位是0

n-bit对齐 = n/8-byte对齐

内存读取对齐:读取n bytes的数据,且数据地址是n-byte对齐的

内存指针对齐:一个指向基本数据类型的指针是n-byte对齐的,如果指针指向的地址只能是n-byte对齐的;一个指向数组或结构体的指针是n-byte对齐的,如果每个基本数据元素都是n-byte对齐的

以上定义假设基本数据类型的大小都是2的幂,否则是否对齐要依情况而定

问题:

内存读取以字为单位,如果字的大小大于最大的基本数据类型,那么对齐内存的读取总是读取单一的字

如果是非对齐内存的读取,即数据的高地址和低地址不在同一个字中,那么对这个数据的读取就要分多次进行,多次读取并把它们整合起来需要更加复杂的电路。而且如果数据在不同的页上,处理器还要在执行指令之前确认这些页是否都在当前内存中,否则还要在执行指令的时候执行TLB缺失或页错误

单一字的读取是原子的,其他的设备将等待当前设备读取该字之后才可以获取它。但是如果是非对齐的数据,在当前设备读取一个字之后,其他的设备可能会改变这个数据,然后当前设备再读取剩下的字,导致脏读问题

数据结构填充:

一个数据结构中的数据成员可能会有不同的对齐要求,所以为保证成员有合适的对齐规则,解释器会填充未命名的数据成员,此外还可能会为数据结构作为一个整体的对齐规则填充未命名成员。这样就能保证无论是所有的数据成员还是作为一个整体都有合适的对齐规则。

在一个成员后面的成员需要更大的对齐方式或者是结构结束的时候才会需要填充,所以改变成员的顺序可以减少填充需要的空间。但是成员按递减的对齐方式排列并不一定保证最小的填充需求。

C和C++不允许编译器重新排列结构的成员,某些语言可能允许。但是C和C++编译器允许指定编译器的对齐等级。如"pack(2)"意味着2-byte对齐,所以填充的成员至多一个字节

一般填充用于节省空间,但也可以用于为一个传输协议格式化数据结构

分配内存时对齐cache线:

对齐cache线的分配内存将会使效率更高。如果数组分为多个线程处理,但是子数组没有对齐cache线,那么会使性能降低。

对齐分配举例:

#include <stdlib.h>
double *foo(void) {
   double *var;//create array of size 10
   int     ok;

ok = posix_memalign((void**)&var, 64, 10*sizeof(double));

if(ok != 0)
     return NULL;

return var;
}
//来自 <https://en.wikipedia.org/wiki/Data_structure_alignment>

硬件的对齐需求:

对齐还可以用于提升硬件水平地址转换的效率(虚拟地址转化为物理地址)

举例:假设有32位操作系统采取4KB大小的页。那么一个页并不是任意的一块区域,而是4KB对齐的内存区域。这会简化硬件把虚拟地址转化为物理地址的代价,硬件上直接把高位地址替换掉,而不必进行更多的计算。

比如TLB把虚拟地址0x2cfc7000映射为物理地址0x12345000,这两个地址都是4KB对齐的,所以当硬件想要把0x2cfc7abc的虚拟地址转化为物理地址的时候只需要把高20位替换为0x12345

一个大小为2^{n+1}-1的数据块总有2^{n}大小的一块是可以进行2^{n}对齐的。所以可以这样申请一块对齐的内存:

// Example: get a 12-bit aligned 4 KBytes buffer with malloc()

// unaligned pointer to large area
void *up = malloc((1 << 13) - 1);
// well-aligned pointer to 4 KBytes
void *ap = aligntonext(up, 12);

//来自 <https://en.wikipedia.org/wiki/Data_structure_alignment>

C运行时栈的对齐实验:

运行环境:gcc version 6.3.0 (MinGW.org GCC-6.3.0-1) on Windows10

在命令行编译运行

代码:

#include <stdio.h>  
int func(void){
    int c;
    printf("stack top in func \t%p\n", &c);
    return 1;
}
void main(void)  { 
    int arr[0];
    int i;  
    printf("stack top before func \t%p\n", &i);
    func();
    return;  
}

结果:

stack top before func   0061FF2C
stack top in func       0061FEFC

调用函数的花费栈空间位48字节。然后改变arr的大小为1:

stack top before func   0061FF28
stack top in func       0061FEFC

然后调用函数花费的栈空间就是44字节。当arr的大小时3的时候调用函数使用的栈空间不再减小,而新的栈花费为52字节

原因:

这是因为运行时栈也是需要对齐的,而且GNU的默认对齐方式是16字节。我在编译时加上选项"-mpreferred-stack-boundary=2"将对齐方式设置为4字节(2^{2}),之后我改变arr的大小,调用函数使用的栈空间只会平移而不会改变大小

在StackOverflow提问的回答:

https://stackoverflow.com/questions/53409162/how-much-stack-space-does-c-exactly-use-for-a-function-activation-record-when-ca

很重要的一点是,在同一个函数中为声明的变量分配栈空间的顺序不一定按照声明的顺序分配,所以不能在函数调用之后声明另一个变量来探测栈顶

参考:

https://en.wikipedia.org/wiki/Data_structure_alignment

转载于:https://www.cnblogs.com/biaoJM/p/10186678.html

### SuperMap 处理无人机倾斜摄影数据的流程及方法 #### 数据预处理阶段 在使用 SuperMap 进行无人机倾斜摄影数据处理之前,需对原始数据进行必要的预处理操作。由于无人机拍摄的照片可能未设置合理的参数限制,导致生成的数据纹理过大,这会显著增加存储空间需求并降低渲染效率[^1]。因此,在此阶段应重点调整瓦片边长以及优化纹理分辨率。 #### 数据导入管理 将经过初步筛选后的倾斜摄影数据导入至 SuperMap 平台中。为了实现更高效的网络共享功能,可以考虑利用成熟的影像传输技术来压缩和分发这些大数据量文件[^2]。具体而言,可以通过配置服务器端支持 RESTful API 接口访问服务形式提供给客户端调用展示。 #### 地形重建三维模型构建 基于上述准备好的素材资料,在软件内部执行自动化或者半自动化的地形重构过程。这一环节涉及到多个关键技术点: - **多视角融合**:不同于传统单一方向获取信息的传统航空遥感手段,现代倾斜摄影采用了五个不同方位角下的同步记录机制(前、后、左、右加上顶部),从而能够全面捕捉目标物体各个侧面特征及其实际高程属性[^4]; - **密集点云提取**:通过对齐配准后的众多重叠区域内的像素对应关系计算得出精确位置坐标集合; - **表面网格划分**:依据前述所得离散采样结果建立连续光滑曲面表示法结构体; 最后一步则是赋予该虚拟实体相应的材质贴图效果完成最终呈现形态转换工作流描述如下所示伪代码片段展示了部分核心逻辑思路仅供参考学习之用并非正式产品级实现版本: ```python def process_tilt_photography(data_path, output_dir): """ Process tilt photography data using a hypothetical workflow. Parameters: data_path (str): Path to the raw drone-captured images. output_dir (str): Directory where processed outputs will be saved. Returns: str: Message indicating success or failure of processing. """ try: # Step 1: Load and preprocess input imagery dataset preprocessed_data = load_and_preprocess_images(data_path) # Step 2: Perform multi-view alignment & dense point cloud generation aligned_clouds = generate_dense_point_cloud(preprocessed_data) # Step 3: Create surface meshes from point clouds meshed_surfaces = create_surface_meshes(aligned_clouds) # Step 4: Apply texture mapping onto generated surfaces textured_model = apply_textures(meshed_surfaces, preprocessed_data['textures']) # Save results into specified directory structure save_results(output_dir, textured_model) return f"Processing completed successfully! Results stored at {output_dir}." except Exception as e: error_message = f"An unexpected error occurred during processing:\n{e}" log_error(error_message) raise RuntimeError(error_message) if __name__ == "__main__": INPUT_DATA_PATH = "/path/to/input/tilt_photos/" OUTPUT_DIRECTORY = "/desired/output/location/" result_status = process_tilt_photography(INPUT_DATA_PATH, OUTPUT_DIRECTORY) print(result_status) ``` 以上脚本仅用于说明概念框架设计原理并不构成完整的解决方案部署方案还需要结合实际情况进一步细化完善各项细节内容才能满足生产环境中的严格要求标准。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值