• 矩阵乘法通过缓存命中率提升运算效率


    矩阵乘法通过缓存命中率提升运算效率 

    1. import numpy as np
    2. n = 512
    3. a = np.full([n,n],1,dtype='int32')
    4. a
    5. b = np.full([n,n],2,dtype='int32')
    6. b
    7. c = np.random.randint(0,5,[n,n])
    8. c
    9. %%timeit
    10. for i in range(0,a.shape[0]):
    11. for j in range(0,b.shape[1]):
    12. for k in range(0,a.shape[1]):
    13. if k == 0:
    14. c[i,j] = 0
    15. c[i,j] += a[i,k]*b[k,j]
    16. %%timeit
    17. for i in range(0,a.shape[0]):
    18. for k in range(0,a.shape[1]):
    19. for j in range(0,b.shape[1]):
    20. if k == 0:
    21. c[i,j] = 0
    22. c[i,j] += a[i,k]*b[k,j]

    测试环境为:ubuntu 18.04

    CPU MHz:             800.682
    CPU max MHz:         2101.0000
    CPU min MHz:         800.0000
    BogoMIPS:            4200.00
    Virtualization:      VT-x
    L1d cache:           32K
    L1i cache:           32K
    L2 cache:            1024K
    L3 cache:            11264K

    这里32KB,一个32位的int占字节数为4B,这里可以L1缓存可以存放8k个int,矩阵相乘每次需要3个矩阵空间,这里测试矩阵宽度为1024

    测试结果为:

    下面采用cpp做了同样的测试,在矩阵维度越大效果越明显。下面依次是矩阵维度在512,1024,2048三个维度下两种矩阵乘法的计算效率。

     代码如下:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. void vec_mul1(const vectorint>> a,const vectorint>> b,vectorint>> c){
    6. for(int i = 0;i < a.size();i++){
    7. for(int j = 0;j < b[0].size();j++){
    8. for(int k = 0;k < a[0].size();k++){
    9. if(k == 0)
    10. c[i][j] = 0;
    11. c[i][j] += a[i][k]*b[k][j];
    12. }
    13. }
    14. }
    15. }
    16. void vec_mul2(const vectorint>> a,const vectorint>> b,vectorint>> c){
    17. for(int i = 0;i < a.size();i++){
    18. for(int k = 0;k < a[0].size();k++){
    19. for(int j = 0;j < b[0].size();j++){
    20. if(k == 0)
    21. c[i][j] = 0;
    22. c[i][j] += a[i][k]*b[k][j];
    23. }
    24. }
    25. }
    26. }
    27. void test(){
    28. int n = 2048;
    29. vectorint>> a(n,vector<int>(n,1));
    30. vectorint>> b(n,vector<int>(n,2));
    31. vectorint>> c(n,vector<int>(n,3));
    32. int loop = 10;
    33. clock_t start,end;
    34. start = clock();
    35. for(int i = 0;i < loop;i++)
    36. vec_mul1(a,b,c);
    37. end = clock();
    38. cout<<"vec multi 1 time = "<<double(end-start)/CLOCKS_PER_SEC/loop<<"s"<
    39. start = clock();
    40. for(int i = 0;i < loop;i++)
    41. vec_mul2(a,b,c);
    42. end = clock();
    43. cout<<"vec multi 2 time = "<<double(end-start)/CLOCKS_PER_SEC/loop<<"s"<
    44. }
    45. int main() {
    46. std::cout << "Hello, World!" << std::endl;
    47. test();
    48. return 0;
    49. }

  • 相关阅读:
    十、网络编程之 poll 详解.md
    internship:一般的原有项目功能优化的具体步骤
    KKSwarm功能升级,低成本实现多车集群与避障
    Vscode 如何创建java项目,并添加包
    图片拼图怎么做?这几种方法可以快速拼图
    javascript中Uint8/16/32Array 传入负数问题
    Docker使用问题汇总
    文件名批量重命名与翻译的实用指南
    (C++)验证回文字符串
    JS异步任务的并行、串行,以及二者结合
  • 原文地址:https://blog.csdn.net/qq_32062657/article/details/126805924