zoukankan      html  css  js  c++  java
  • 一个矩阵乘法的问题

    问题:1024阶双精度浮点矩阵相乘,矩阵满秩

    经典代码:

    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            for (k = 0; k < N; k++)
            {
                c[i*N+j] = c[i*N+j] + a[i*N+k]*b[k*N+j];
            }
        }
    }

    这是比较经典的方式,发现一个问题,1024阶的时间居然比1025阶的时间多不少,很令人费解,于是加了一些类似gettimeofday这种函数统计计算每一个行,每一个结果的时间,发现在1024的时候没隔一定个数的元素,时间都会有一个比较大的增加(一般是加倍),而1025则不会,个人的猜想是cache造成的影响,1024的情况,每行正好是cache line size的整数倍,而1025则不是,可能会有一些预取,而在这种乘法访问顺序的情况下,会出现“跳着”访问,这样这些预取就会使得性能有所提升。

    对原有乘法做一些改变:

    for (i = 0; i < N; i++)
    {
        for (k = 0; k < N; k++)
        {
            for (j = 0; j < N; j++)
            {
                c[i*N+j] = c[i*N+j] + a[i*N+k]*b[k*N+j];
            }
        }
    }

    师兄说这是一个比较经典的矩阵相乘方法,自习想了想才想通,字面上看是把二三层的循环调换了一下顺序,其实把加法均摊,实现了对a数组、b数组都顺序访问,这样就是cache性能提升了很多,整体性能就提升了,而且这样修改后,1025和1024的时间也正常了,阶数多的时间长。

    完整代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/time.h>
    
    //#define N 1023
    int main(int argc, char* argv[])
    {
        double *a, *b, *c;
        int i, j, k;
        int N;
        struct timeval start, end;
        N = atoi(argv[1]);
        a = (double*)malloc(N*N*sizeof(double));
        b = (double*)malloc(N*N*sizeof(double));
        c = (double*)malloc(N*N*sizeof(double));
        for (i = 0; i < N; i++)
        {
            for (j = 0; j < N; j++)
            {
                a[i*N+j] = 2.0;
                b[i*N+j] = 1.0;
                c[i*N+j] = 0;
            }
        }
    
        gettimeofday(&start, NULL);
    
        for (i = 0; i < N; i++)
        {
            for (k = 0; k < N; k++)
            {
                for (j = 0; j < N; j++)
                {
                    c[i*N+j] = c[i*N+j] + a[i*N+k]*b[k*N+j];
                }
            }
        }
    
        gettimeofday(&end, NULL);
        printf("line %d	%d
    ", i, 1000000*(end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec);
        free(a);
        free(b);
        free(c);
        return 0;
    }
  • 相关阅读:
    C# 中 finally 的用法
    相似度算法(转载)
    OpenCV 安装与调试
    win7 debug 工具
    wpf 登录时显示状态动态图
    C# 比较两张图片是否完全相同
    ABSD 基于架构的软件设计方法方法简介(摘抄)
    基于SQL Server的简单数据同步方案
    软件:产品和过程的统一(转)
    cpp extern 关键字用法
  • 原文地址:https://www.cnblogs.com/pocean/p/3691015.html
Copyright © 2011-2022 走看看