C语言2048阶矩阵乘法计时及const数组随机初始化问题
2048×2048矩阵乘法耗时测算实现方案
核心问题修复逻辑
两个问题可按规则解决,不需要修改现有matrixMult函数和gettimeofday计时框架的接口:
- 全局const指针无有效内存:
const float*类型的指针仅限制指向的内容不可修改,指针本身的指向可以变更,禁止直接在栈上分配大矩阵(单矩阵占16MB,栈空间默认通常仅8MB会直接溢出),统一在堆上申请内存。 - const数组随机初始化:不要直接对const指向的内存做写入操作(会触发编译错误+未定义行为),申请内存时先用可写的临时浮点指针操作,完成随机值填充后再把地址赋值给const类型的A、B指针,完全符合const语义要求。
完整实现步骤
1. 基础定义与内存分配
先统一宏定义矩阵维度,避免魔法数,再完成三个矩阵的堆内存申请与合法性校验:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include <time.h> #define MAT_DIM 2048 #define TOTAL_ELEM (MAT_DIM * MAT_DIM) // 全局指针声明,和现有框架保持一致 const float *A, *B; float *C; // 外部传入的矩阵乘法函数,签名匹配通用实现 extern void matrixMult(const float* A, const float* B, float* C, int n);
内存分配逻辑放在程序初始化阶段(main函数开头即可):
// 用可写临时指针申请A、B的内存,用于后续初始化 float* tmp_A = (float*)malloc(sizeof(float) * TOTAL_ELEM); float* tmp_B = (float*)malloc(sizeof(float) * TOTAL_ELEM); C = (float*)malloc(sizeof(float) * TOTAL_ELEM); if (!tmp_A || !tmp_B || !C) { perror("memory alloc failed"); exit(EXIT_FAILURE); }
2. 随机值初始化
随机种子仅初始化1次即可,填充[0,1)范围的浮点值,避免数值过大导致乘法结果溢出float精度范围:
srand((unsigned int)time(NULL)); for (int i = 0; i < TOTAL_ELEM; i++) { tmp_A[i] = (float)rand() / (float)(RAND_MAX + 1.0f); tmp_B[i] = (float)rand() / (float)(RAND_MAX + 1.0f); } // 初始化完成后,将内存地址挂载到const全局指针,后续不可通过A、B修改矩阵内容 A = tmp_A; B = tmp_B;
3. 10组计时样本采集
基于现有gettimeofday框架实现,每次计时前清空输出矩阵C的残留值,避免干扰计算逻辑:
// 时间差计算工具函数,返回单位:毫秒 static double get_elapsed_ms(struct timeval start, struct timeval end) { return (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_usec - start.tv_usec) / 1000.0; } int main() { // 此处放前面的内存分配、初始化逻辑 // 可选:预跑1次矩阵乘法,加载CPU/指令缓存,避免第一组冷启动数据偏差 memset(C, 0, sizeof(float) * TOTAL_ELEM); matrixMult(A, B, C, MAT_DIM); const int sample_num = 10; double total_cost = 0.0; for (int s = 0; s < sample_num; s++) { memset(C, 0, sizeof(float) * TOTAL_ELEM); struct timeval t_start, t_end; gettimeofday(&t_start, NULL); matrixMult(A, B, C, MAT_DIM); gettimeofday(&t_end, NULL); double cost = get_elapsed_ms(t_start, t_end); printf("Sample %d cost: %.2f ms\n", s+1, cost); total_cost += cost; } printf("Average cost of 10 samples: %.2f ms\n", total_cost / sample_num); // 退出前释放内存 free((void*)A); free((void*)B); free(C); return 0; }
关键注意事项
- 编译时必须开启
-O2或更高等级优化,debug模式(-O0)下的矩阵乘法耗时没有性能参考价值。 - 不要强制转换const指针直接写入内容,比如
*(float*)A = xxx,属于C标准定义的未定义行为,可能触发运行时段错误。 - 如果需要更精准的计时,可以在测试时关闭CPU睿频、固定CPU频率,避免频率波动导致样本数据离散度过大。
- 不需要每次采集样本都重新初始化A、B矩阵,重复填充随机值会引入额外耗时,干扰计时结果。
内容的提问来源于stack exchange,提问作者mitousis
相关产品推荐
相关产品推荐

