Compare commits

..

5 Commits
main ... 555

@ -0,0 +1,129 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <arm_neon.h> // 包含 NEON 头文件
#define SIZE 1024 // 定义矩阵大小
#define ALIGNMENT 16 // NEON要求的数据对齐
// 动态分配对齐的二维数组
float** allocate_2d_array(int rows, int cols) {
float** array = (float**)malloc(rows * sizeof(float*));
if (!array) {
fprintf(stderr, "Memory allocation failed for 2D array.\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < rows; ++i) {
array[i] = (float*)aligned_alloc(ALIGNMENT, cols * sizeof(float));
if (!array[i]) {
fprintf(stderr, "Memory allocation failed for row %d.\n", i);
// 释放已经分配的内存
for (int j = 0; j < i; ++j) {
free(array[j]);
}
free(array);
exit(EXIT_FAILURE);
}
}
return array;
}
// 释放二维数组
void free_2d_array(float** array, int rows) {
for (int i = 0; i < rows; ++i) {
free(array[i]);
}
free(array);
}
// 基础矩阵乘法函数
void matmul(float** A, float** B, float** C, int n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
C[i][j] = 0; // 初始化 C[i][j]
for (int k = 0; k < n; ++k) {
C[i][j] += A[i][k] * B[k][j]; // 逐项累加计算结果
}
}
}
}
// NEON 优化矩阵乘法函数
void matmul_optimized(float** A, float** B, float** C, int n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
float32x4_t vecC = vdupq_n_f32(0.0); // 初始化结果向量 vecC 为 0
for (int k = 0; k <= n - 4; k += 4) { // 确保不会越界
// 加载矩阵 A 和 B 的 4 个连续元素
float32x4_t vecA = vld1q_f32(&A[i][k]);
float32x4_t vecB = vld1q_f32(&B[k][j]);
// 执行向量化乘法和累加
vecC = vmlaq_f32(vecC, vecA, vecB);
}
// 还原向量结果到 C[i][j]
C[i][j] = vaddvq_f32(vecC);
// 处理剩余元素(如果 n 不是 4 的倍数)
for (int k = n & ~3; k < n; ++k) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
}
int main() {
// 检查是否支持NEON
#if !defined(__ARM_NEON)
printf("Error: This compiler does not support ARM NEON.\n");
return 1;
#endif
// 动态分配矩阵 A、B、C 和 C_optimized 的内存
float** A = allocate_2d_array(SIZE, SIZE);
float** B = allocate_2d_array(SIZE, SIZE);
float** C = allocate_2d_array(SIZE, SIZE);
float** C_optimized = allocate_2d_array(SIZE, SIZE);
// 初始化矩阵 A 和 B 的元素
srand(time(0));
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
A[i][j] = rand() % 100; // 生成 0 到 99 的随机数
B[i][j] = rand() % 100;
}
}
// 计时并进行基础矩阵乘法
clock_t start = clock();
matmul(A, B, C, SIZE); // 执行基础矩阵乘法
clock_t end = clock();
printf("基础矩阵乘法运行时间: %.6f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
// 计时并进行 NEON 优化矩阵乘法
start = clock();
matmul_optimized(A, B, C_optimized, SIZE); // 执行 NEON 优化矩阵乘法
end = clock();
printf("NEON 优化矩阵乘法运行时间: %.6f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
// 验证结果
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
if (C[i][j] != C_optimized[i][j]) {
printf("Results do not match at index (%d, %d): %f vs %f\n", i, j, C[i][j], C_optimized[i][j]);
break;
}
}
}
// 释放矩阵 A、B、C、C_optimized 的内存
free_2d_array(A, SIZE);
free_2d_array(B, SIZE);
free_2d_array(C, SIZE);
free_2d_array(C_optimized, SIZE);
return 0;
}

@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 定义稀疏矩阵的结构体
typedef struct {
float* values; // 存储非零元素的值
int* rowIndex; // 存储非零元素的行索引
int* colIndex; // 存储非零元素的列索引
int nonZeroCount; // 非零元素的总数量
int rows; // 矩阵的总行数
int cols; // 矩阵的总列数
} SparseMatrix;
// 初始化稀疏矩阵
SparseMatrix create_sparse_matrix(int rows, int cols, int nonZeroCount) {
SparseMatrix mat;
mat.values = (float*)malloc(nonZeroCount * sizeof(float));
mat.rowIndex = (int*)malloc(nonZeroCount * sizeof(int));
mat.colIndex = (int*)malloc(nonZeroCount * sizeof(int));
mat.nonZeroCount = nonZeroCount;
mat.rows = rows;
mat.cols = cols;
return mat;
}
// 释放稀疏矩阵内存
void free_sparse_matrix(SparseMatrix* mat) {
free(mat->values);
free(mat->rowIndex);
free(mat->colIndex);
}
// 稀疏矩阵乘法
void sparse_matmul(SparseMatrix* A, SparseMatrix* B, SparseMatrix* C) {
// 假设 A 的列数等于 B 的行数
for (int i = 0; i < A->nonZeroCount; ++i) {
for (int j = 0; j < B->nonZeroCount; ++j) {
// 如果 A 的列索引和 B 的行索引相同
if (A->colIndex[i] == B->rowIndex[j]) {
int row = A->rowIndex[i];
int col = B->colIndex[j];
// 更新结果矩阵
for (int k = 0; k < C->nonZeroCount; ++k) {
if (C->rowIndex[k] == row && C->colIndex[k] == col) {
C->values[k] += A->values[i] * B->values[j];
break;
}
}
}
}
}
}
// 打印稀疏矩阵
void print_sparse_matrix(SparseMatrix* mat) {
printf("Sparse Matrix:\n");
for (int i = 0; i < mat->nonZeroCount; ++i) {
printf("Value: %f, Row: %d, Col: %d\n", mat->values[i], mat->rowIndex[i], mat->colIndex[i]);
}
}
int main() {
// 初始化稀疏矩阵 A 和 B
int rows = 4, cols = 4, nonZeroCountA = 4, nonZeroCountB = 4;
SparseMatrix A = create_sparse_matrix(rows, cols, nonZeroCountA);
SparseMatrix B = create_sparse_matrix(rows, cols, nonZeroCountB);
// 初始化 A 和 B 矩阵中的非零元素
srand(time(0));
for (int i = 0; i < nonZeroCountA; ++i) {
A.values[i] = rand() % 10 + 1;
A.rowIndex[i] = i % rows; // 为了简化,这里使用简单的模式
A.colIndex[i] = i % cols;
}
for (int i = 0; i < nonZeroCountB; ++i) {
B.values[i] = rand() % 10 + 1;
B.rowIndex[i] = i % rows; // 为了简化,这里使用简单的模式
B.colIndex[i] = i % cols;
}
// 初始化结果矩阵 C
SparseMatrix C = create_sparse_matrix(rows, cols, nonZeroCountA * nonZeroCountB); // 最坏情况下的非零元素数量
for (int i = 0; i < C.nonZeroCount; ++i) {
C.values[i] = 0;
C.rowIndex[i] = -1; // 标记为未使用
C.colIndex[i] = -1;
}
// 计时并进行稀疏矩阵乘法
clock_t start = clock();
sparse_matmul(&A, &B, &C); // 执行稀疏矩阵乘法
clock_t end = clock();
printf("稀疏矩阵乘法运行时间: %.6f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
// 打印结果矩阵
print_sparse_matrix(&C);
// 释放稀疏矩阵 A、B、C 的内存
free_sparse_matrix(&A);
free_sparse_matrix(&B);
free_sparse_matrix(&C);
return 0;
}

@ -0,0 +1,46 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 1024
// 向量加法函数
void vector_add(float* A, float* B, float* C, int size) {
for (int i = 0; i < size; ++i) { // 在循环内部声明i
C[i] = A[i] + B[i];
}
}
int main() {
// 定义向量
float A[SIZE], B[SIZE], C[SIZE];
// 初始化随机数种子
srand(time(0));
// 初始化向量 A 和 B
for (int i = 0; i < SIZE; ++i) { // 在循环内部声明i
A[i] = (float)(rand() % 100) / 100.0f; // 生成0到1之间的浮点数
B[i] = (float)(rand() % 100) / 100.0f;
}
// 多次执行以获得更准确的时间测量
const int NUM_ITERATIONS = 1000;
clock_t total_time = 0;
for (int j = 0; j < NUM_ITERATIONS; ++j) {
clock_t start = clock();
vector_add(A, B, C, SIZE); // 执行向量加法
clock_t end = clock();
total_time += (end - start);
}
// 输均运行时间
printf("基础向量加法平均运行时间: %.6f 秒\n", (double)total_time / (CLOCKS_PER_SEC * NUM_ITERATIONS));
// 可选:验证前几个元素的结果
for (int k = 0; k < 5; ++k) {
printf("A[%d] + B[%d] = C[%d]: %.2f + %.2f = %.2f\n", k, k, k, A[k], B[k], C[k]);
}
return 0;
}

@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 1024 // 定义矩阵大小
#define ALIGNMENT 64 // 对齐大小
// 动态分配对齐的二维数组
float** allocate_2d_array(int rows, int cols) {
float** array = (float**)malloc(rows * sizeof(float*));
if (!array) {
fprintf(stderr, "Memory allocation failed for 2D array.\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < rows; ++i) {
array[i] = (float*)aligned_alloc(ALIGNMENT, cols * sizeof(float));
if (!array[i]) {
fprintf(stderr, "Memory allocation failed for row %d.\n", i);
// 释放已经分配的内存
for (int j = 0; j < i; ++j) {
free(array[j]);
}
free(array);
exit(EXIT_FAILURE);
}
}
return array;
}
// 释放二维数组
void free_2d_array(float** array, int rows) {
for (int i = 0; i < rows; ++i) {
free(array[i]);
}
free(array);
}
// 矩阵乘法函数
void matmul(float** A, float** B, float** C, int n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
C[i][j] = 0; // 初始化 C[i][j]
for (int k = 0; k < n; ++k) {
C[i][j] += A[i][k] * B[k][j]; // 逐项累加计算结果
}
}
}
}
int main() {
// 动态分配矩阵 A、B、C 的内存
float** A = allocate_2d_array(SIZE, SIZE);
float** B = allocate_2d_array(SIZE, SIZE);
float** C = allocate_2d_array(SIZE, SIZE);
// 初始化矩阵 A 和 B 的元素
srand(time(0));
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
A[i][j] = rand() % 100; // 生成 0 到 99 的随机数
B[i][j] = rand() % 100;
}
}
// 多次执行以获得更准确的时间测量
const int NUM_ITERATIONS = 10;
clock_t total_time = 0;
for (int iter = 0; iter < NUM_ITERATIONS; ++iter) {
clock_t start = clock();
matmul(A, B, C, SIZE); // 执行矩阵乘法
clock_t end = clock();
total_time += (end - start);
}
// 输出平均运行时间
printf("基础矩阵乘法平均运行时间: %.6f 秒\n", (double)total_time / (CLOCKS_PER_SEC * NUM_ITERATIONS));
// 释放矩阵 A、B、C 的内存
free_2d_array(A, SIZE);
free_2d_array(B, SIZE);
free_2d_array(C, SIZE);
return 0;
}

@ -0,0 +1,83 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <arm_neon.h> // 包含 NEON 头文件
#define SIZE 1024 // 定义向量大小
#define ALIGNMENT 16 // NEON要求的数据对齐
// 基础向量加法函数
void vector_add(float* A, float* B, float* C, int size) {
for (int i = 0; i < size; ++i) {
C[i] = A[i] + B[i];
}
}
// NEON 优化向量加法函数
void vector_add_optimized(float* A, float* B, float* C, int size) {
for (int i = 0; i <= size - 4; i += 4) { // 确保不会越界
float32x4_t vecA = vld1q_f32(&A[i]);
float32x4_t vecB = vld1q_f32(&B[i]);
float32x4_t vecC = vaddq_f32(vecA, vecB);
vst1q_f32(&C[i], vecC);
}
// 处理剩余元素(如果 size 不是 4 的倍数)
for (int i = size & ~3; i < size; ++i) { // 使用位操作确保从最近的4的倍数开始
C[i] = A[i] + B[i];
}
}
int main() {
// 检查是否支持NEON
#if !defined(__ARM_NEON)
printf("Error: This compiler does not support ARM NEON.\n");
return 1;
#endif
// 定义并初始化对齐的向量
float *A = (float *)aligned_alloc(ALIGNMENT, SIZE * sizeof(float));
float *B = (float *)aligned_alloc(ALIGNMENT, SIZE * sizeof(float));
float *C = (float *)aligned_alloc(ALIGNMENT, SIZE * sizeof(float));
float *C_optimized = (float *)aligned_alloc(ALIGNMENT, SIZE * sizeof(float));
if (!A || !B || !C || !C_optimized) {
printf("Memory allocation failed.\n");
free(A); free(B); free(C); free(C_optimized);
return 1;
}
// 初始化随机数种子
srand(time(0));
// 初始化向量 A 和 B
for (int i = 0; i < SIZE; ++i) {
A[i] = rand() % 100; // 生成 0 到 99 的随机数
B[i] = rand() % 100;
}
// 基础向量加法计时
clock_t start = clock();
vector_add(A, B, C, SIZE); // 执行基础向量加法
clock_t end = clock();
printf("基础向量加法运行时间: %.6f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
// NEON 优化向量加法计时
start = clock();
vector_add_optimized(A, B, C_optimized, SIZE); // 执行 NEON 优化向量加法
end = clock();
printf("NEON 优化向量加法运行时间: %.6f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
// 验证结果
for (int i = 0; i < SIZE; ++i) {
if (C[i] != C_optimized[i]) {
printf("Results do not match at index %d: %f vs %f\n", i, C[i], C_optimized[i]);
break;
}
}
// 释放内存
free(A); free(B); free(C); free(C_optimized);
return 0;
}
Loading…
Cancel
Save