文章目录
向量化
通俗来说在列式存储的数据库里来说,如果要对数据进行累加运行,如果每次只能操作一个数,必然效率低下,向量操作就是就是采用SIMD技术,通过一个指令,实现对多个数据的处理
使用场景
通常会用在列式数据库,作分析数据使用。 比如clickhouse
代码说明
通常代码来详细展示使用向量和传统方式实现相加的实现方式
bash
#include <iostream>
#include <arm_neon.h> // 包含 ARM NEON SIMD 指令集的头文件
#include <chrono> // 用于计时的头文件
void vector_add_neon(const float32_t* a, const float32_t* b, float32_t* result, size_t n) {
size_t i = 0;
for (; i + 4 <= n; i += 4) {
float32x4_t va = vld1q_f32(a + i); // 加载 4 个浮点数到 NEON 寄存器 va
float32x4_t vb = vld1q_f32(b + i); // 加载 4 个浮点数到 NEON 寄存器 vb
float32x4_t vr = vaddq_f32(va, vb); // 对寄存器 va 和 vb 中的浮点数逐元素相加
vst1q_f32(result + i, vr); // 将结果存储回内存
}
for (; i < n; ++i) {
result[i] = a[i] + b[i];
}
}
void vector_add_basic(const float* a, const float* b, float* result, size_t n) {
for (size_t i = 0; i < n; ++i) {
result[i] = a[i] + b[i];
}
}
int main() {
const size_t n = 1000000; // 数组长度增加到 100 万
float32_t a[n];
float32_t b[n];
float32_t result_neon[n];
float32_t result_basic[n];
// 初始化数组 a 和 b
for (size_t i = 0; i < n; ++i) {
a[i] = static_cast<float32_t>(i);
b[i] = static_cast<float32_t>(i * 2);
}
// 测量使用 NEON SIMD 的计算时间
auto start_neon = std::chrono::high_resolution_clock::now();
vector_add_neon(a, b, result_neon, n);
auto end_neon = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_neon = end_neon - start_neon;
// 测量普通循环计算时间
auto start_basic = std::chrono::high_resolution_clock::now();
vector_add_basic(a, b, result_basic, n);
auto end_basic = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_basic = end_basic - start_basic;
// 输出结果
std::cout << "NEON SIMD 加速耗时: " << elapsed_neon.count() << " 秒\n";
std::cout << "普通循环耗时: " << elapsed_basic.count() << " 秒\n";
return 0;
}