存储为 helloGemm_1x1.cpp
编译:
g++ hello_gemm_1x1.cpp -o hello_gemm_1x1.out -O3
- #include
- #include
-
-
- using namespace std;
-
- void gemm_A_N_B_T_1x1(float* A, float* B, float* C, int M_, int N_, int K_){
-
- for(int i=0; i
- for(int j=0; j
- for(int k=0; k
- C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
- void gemm_A_N_B_T_2x2(float* A, float* B, float* C, int M_, int N_, int K_){
-
- register float a1, a2, b1, b2;
-
- for(int i=0; i
2; i++){ - for(int j=0; j
2; j++){ - for(int k=0; k
- a1 = A[2*i + k*M_ ];//2*i k
- a2 = A[(2*i+1) + k*M_ ];//2*i+1 k
- b1 = B[k*N_ + 2*j ];//k 2*j
- b2 = B[k*N_ + (2*j+1)];//k 2*j+1
-
- C[2*i + 2*j*M_ ] += a1*b1;
- C[2*i + (2*j+1)*M_] += a1*b2;
- C[(2*i+1) + 2*j*M_ ] += a2*b1;
- C[2*i+1 + (2*j+1)*M_] += a2*b2;
- // C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
-
-
- void init_mat(float* A, int count, int mod){
- for(int idx=0; idx
- A[idx] = idx%mod + 1;
- }
- }
-
-
- void print_mat(float* A, int M, int N, bool colMajor){
-
- cout<
-
- for(int i=0; i
- for(int j=0; j
- cout<<" "<<(colMajor? A[i + j*M]: A[i*N + j]);
- }
- cout<
- }
- }
-
-
-
- int main(){
-
-
- int M = 1024;
- int N = 1024;
- int K = 1024;
-
- float* A = nullptr;
- float* B = nullptr;
- float* C_1x1 = nullptr;
- float* C_2x2 = nullptr;
-
- A = (float*)malloc(M*K*sizeof(float));
- B = (float*)malloc(K*N*sizeof(float));
- C_1x1 = (float*)malloc(M*N*sizeof(float));
- C_2x2 = (float*)malloc(M*N*sizeof(float));
-
- init_mat(A, M*K, 3);
- init_mat(B, K*N, 4);
-
- // print_mat(A, M, K, true);
- // print_mat(B, K, N, false);
-
- gemm_A_N_B_T_1x1(A, B, C_1x1, M, N, K);
- // gemm_A_N_B_T_2x2(A, B, C_2x2, M, N, K);
-
- //print_mat(C_1x1, M, N, true);
- //print_mat(C_2x2, M, N, true);
-
- cout<
"C(M,N)"<< C_1x1[M*N-1]< - // cout<
-
-
-
-
-
- return 0;
- }
二,block2x2 register 优化
存储为 helloGemm_2x2.cpp
编译:
g++ hello_gemm_2x2.cpp -o hello_gemm_2x2.out -O3
- #include
- #include
-
-
- using namespace std;
-
- void gemm_A_N_B_T_1x1(float* A, float* B, float* C, int M_, int N_, int K_){
-
- for(int i=0; i
- for(int j=0; j
- for(int k=0; k
- C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
- void gemm_A_N_B_T_2x2(float* A, float* B, float* C, int M_, int N_, int K_){
-
- register float a1, a2, b1, b2;
-
- for(int i=0; i
2; i++){ - for(int j=0; j
2; j++){ - for(int k=0; k
- a1 = A[2*i + k*M_ ];//2*i k
- a2 = A[(2*i+1) + k*M_ ];//2*i+1 k
- b1 = B[k*N_ + 2*j ];//k 2*j
- b2 = B[k*N_ + (2*j+1)];//k 2*j+1
-
- C[2*i + 2*j*M_ ] += a1*b1;
- C[2*i + (2*j+1)*M_] += a1*b2;
- C[(2*i+1) + 2*j*M_ ] += a2*b1;
- C[2*i+1 + (2*j+1)*M_] += a2*b2;
- // C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
-
-
- void init_mat(float* A, int count, int mod){
- for(int idx=0; idx
- A[idx] = idx%mod + 1;
- }
- }
-
-
- void print_mat(float* A, int M, int N, bool colMajor){
-
- cout<
-
- for(int i=0; i
- for(int j=0; j
- cout<<" "<<(colMajor? A[i + j*M]: A[i*N + j]);
- }
- cout<
- }
- }
-
-
-
- int main(){
-
-
- int M = 1024;
- int N = 1024;
- int K = 1024;
-
- float* A = nullptr;
- float* B = nullptr;
- float* C_1x1 = nullptr;
- float* C_2x2 = nullptr;
-
- A = (float*)malloc(M*K*sizeof(float));
- B = (float*)malloc(K*N*sizeof(float));
- C_1x1 = (float*)malloc(M*N*sizeof(float));
- C_2x2 = (float*)malloc(M*N*sizeof(float));
-
- init_mat(A, M*K, 3);
- init_mat(B, K*N, 4);
-
- // print_mat(A, M, K, true);
- // print_mat(B, K, N, false);
-
- // gemm_A_N_B_T_1x1(A, B, C_1x1, M, N, K);
- gemm_A_N_B_T_2x2(A, B, C_2x2, M, N, K);
-
- //print_mat(C_1x1, M, N, true);
- //print_mat(C_2x2, M, N, true);
-
- // cout<
- cout<
"C(M,N)"<< C_2x2[M*N-1]< -
-
-
-
-
- return 0;
- }
(m, n, k) = (1024, 1024, 1024)
加速效果明显, 效果图: 2 second VS 5 second

加入 openmp后,并行效果更加明显:
三,使用openmp对三重for循环优化
将测试 size 全部改成: ((m, n, k) = (1024, 1024, 4096))
在上面个的两个版本基础上,加入openmp加速指令后的代码为:
存储为 helloGemm_1x1_omp.cpp
编译:
g++ hello_gemm_1x1_omp.cpp -o hello_gemm_1x1_omp.out -O3 -fopenmp
- #include
- #include
- #include
-
- using namespace std;
-
- void gemm_A_N_B_T_1x1(float* A, float* B, float* C, int M_, int N_, int K_){
-
- #pragma omp parallel for num_threads(omp_get_num_procs())
- for(int i=0; i
- for(int j=0; j
- for(int k=0; k
- C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
- void gemm_A_N_B_T_2x2(float* A, float* B, float* C, int M_, int N_, int K_){
-
- // register float a1, a2, b1, b2;
- #pragma omp parallel for num_threads(omp_get_num_procs())
- for(int i=0; i
2; i++){ - for(int j=0; j
2; j++){ - for(int k=0; k
- register float a1, a2, b1, b2;
-
- a1 = A[2*i + k*M_ ];//2*i k
- a2 = A[(2*i+1) + k*M_ ];//2*i+1 k
- b1 = B[k*N_ + 2*j ];//k 2*j
- b2 = B[k*N_ + (2*j+1)];//k 2*j+1
-
- C[2*i + 2*j*M_ ] += a1*b1;
- C[2*i + (2*j+1)*M_] += a1*b2;
- C[(2*i+1) + 2*j*M_ ] += a2*b1;
- C[2*i+1 + (2*j+1)*M_] += a2*b2;
- // C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
-
-
- void init_mat(float* A, int count, int mod){
- for(int idx=0; idx
- A[idx] = idx%mod + 1;
- }
- }
-
-
- void print_mat(float* A, int M, int N, bool colMajor){
-
- cout<
-
- for(int i=0; i
- for(int j=0; j
- cout<<" "<<(colMajor? A[i + j*M]: A[i*N + j]);
- }
- cout<
- }
- }
-
-
-
- int main(){
-
-
- int M = 1024;
- int N = 1024;
- int K = 4096;
-
- float* A = nullptr;
- float* B = nullptr;
- float* C_1x1 = nullptr;
- float* C_2x2 = nullptr;
-
- A = (float*)malloc(M*K*sizeof(float));
- B = (float*)malloc(K*N*sizeof(float));
- C_1x1 = (float*)malloc(M*N*sizeof(float));
- C_2x2 = (float*)malloc(M*N*sizeof(float));
-
- init_mat(A, M*K, 3);
- init_mat(B, K*N, 4);
-
- // print_mat(A, M, K, true);
- // print_mat(B, K, N, false);
-
- gemm_A_N_B_T_1x1(A, B, C_1x1, M, N, K);
- // gemm_A_N_B_T_2x2(A, B, C_2x2, M, N, K);
-
- //print_mat(C_1x1, M, N, true);
- //print_mat(C_2x2, M, N, true);
-
- cout<
"C(M,N)"<< C_1x1[M*N-1]< - // cout<
-
-
-
-
-
- return 0;
- }
四,对block2x2 register 优化加入 openmp加速
存储为 helloGemm_2x2_omp.cpp
g++ hello_gemm_2x2_omp.cpp -o hello_gemm_2x2_omp.out -O3 -fopenmp
- #include
- #include
- #include
-
- using namespace std;
-
- void gemm_A_N_B_T_1x1(float* A, float* B, float* C, int M_, int N_, int K_){
-
- #pragma omp parallel for num_threads(omp_get_num_procs())
- for(int i=0; i
- for(int j=0; j
- for(int k=0; k
- C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
- void gemm_A_N_B_T_2x2(float* A, float* B, float* C, int M_, int N_, int K_){
-
- // register float a1, a2, b1, b2;
- #pragma omp parallel for num_threads(omp_get_num_procs())
- for(int i=0; i
2; i++){ - for(int j=0; j
2; j++){ - for(int k=0; k
- register float a1, a2, b1, b2;
-
- a1 = A[2*i + k*M_ ];//2*i k
- a2 = A[(2*i+1) + k*M_ ];//2*i+1 k
- b1 = B[k*N_ + 2*j ];//k 2*j
- b2 = B[k*N_ + (2*j+1)];//k 2*j+1
-
- C[2*i + 2*j*M_ ] += a1*b1;
- C[2*i + (2*j+1)*M_] += a1*b2;
- C[(2*i+1) + 2*j*M_ ] += a2*b1;
- C[2*i+1 + (2*j+1)*M_] += a2*b2;
- // C[i + j*M_] += A[i + k*M_]*B[k*N_ + j];
- }
- }
- }
-
- }
-
-
-
- void init_mat(float* A, int count, int mod){
- for(int idx=0; idx
- A[idx] = idx%mod + 1;
- }
- }
-
-
- void print_mat(float* A, int M, int N, bool colMajor){
-
- cout<
-
- for(int i=0; i
- for(int j=0; j
- cout<<" "<<(colMajor? A[i + j*M]: A[i*N + j]);
- }
- cout<
- }
- }
-
-
-
- int main(){
-
-
- int M = 1024;//2048;
- int N = 1024;//2048;
- int K = 4096;
-
- float* A = nullptr;
- float* B = nullptr;
- float* C_1x1 = nullptr;
- float* C_2x2 = nullptr;
-
- A = (float*)malloc(M*K*sizeof(float));
- B = (float*)malloc(K*N*sizeof(float));
- C_1x1 = (float*)malloc(M*N*sizeof(float));
- C_2x2 = (float*)malloc(M*N*sizeof(float));
-
- init_mat(A, M*K, 3);
- init_mat(B, K*N, 4);
-
- // print_mat(A, M, K, true);
- // print_mat(B, K, N, false);
-
- // gemm_A_N_B_T_1x1(A, B, C_1x1, M, N, K);
- gemm_A_N_B_T_2x2(A, B, C_2x2, M, N, K);
-
- //print_mat(C_1x1, M, N, true);
- //print_mat(C_2x2, M, N, true);
-
- // cout<
- cout<
"C(M,N)"<< C_2x2[M*N-1]< -
-
-
-
-
- return 0;
- }
编译图:

效果图:

优化效果统计:
三重for循环: 43 s
block2x2 register: 11 s
openmp 三重for循环: 2 s
openmp block2x2 register: 1s
-
相关阅读:
【Tableau Server 企业日常问题 24】Tableau server提示工具嵌入工作表,服务器字体乱码问题解决
数据结构之——队列详解 ( 1 )
【无标题】
人工智能行业源代码防数据防泄密需求分析
MIPI CSI-2笔记(15) -- 数据格式(简介、通用8-bit长包数据类型)
js中如何判断一个变量是否为数字类型?
【网络技术】【Kali Linux】Wireshark嗅探(十一)以太网Ethernet协议报文捕获及分析
道可云元宇宙每日资讯|上海多个热门元宇宙文旅项目迎来消费高峰
ByteHouse云数仓版查询性能优化和MySQL生态完善
获取数据类型的方式和typescript is 类型谓词
-
原文地址:https://blog.csdn.net/eloudy/article/details/126698509
-
最新文章
-
沪漂五周年了:我越来越迷茫了
Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
MySQL-Seconds_behind_master的精度误差
[MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
Agent OS :五种驯服不确定性的范式
PortSwigger SQL注入LAB11
数据库即时编译JIT
[Begin]AI Learn Data Day 0
深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU