• 矩阵按列相乘运算的并行化实现方法


            这两天一直在琢磨如下矩阵计算问题。

            已知d×m矩阵X和h×q矩阵Y,求如下矩阵:

    其中X(:,i), Y(:,j)分别表示矩阵X, Y的第i列和第j列,易知Z为d×h矩阵。

            如果直接串行计算矩阵Z,两个循环共有m×q,则会很慢,能不能并行化呢?

            实际上是可以的,为便于理解,我们先把Z写成如下形式:

    对于矩阵Z中的第(r,s)个元素:

    .

    注意到第一个括号是X的第r行之和,第二个括号是Y的第s行之和。

            也就是说,矩阵Z中的第(r,s)个元素等于X的第r行之和乘以Y的第s行之和。因此,可以先分别将X和Y所有列对应相加,得到长为d的列向量Xsum和长为h的列向量Ysum,则Z等于Xsum乘以Ysum的转置。实际上,推导可以不用这么麻烦,对于目标计算式:

     

    注意到第一个括号是将X所有列对应相加,第二个括号是将Y所有列对应相加,因此Z也就是前面提到的Xsum乘以Ysum的转置。

            Matlab代码如下:

    1. function [ Z ] = Mtx_Col_Multi( X, Y )
    2. % Mtx_Col_Multi returns Z = \sum_{i=1}^{m}\sum_{j=1}^{q} X(:,i)*Y(:,j)'
    3. % Here, X(:,i) and Y(:,j) denote the i-th and j-th column of X and Y, respectively
    4. % INPUT:
    5. % X - A dxm matrix
    6. % Y - A hxq matrix
    7. % OUTPUT:
    8. % Z - A dxh matrix
    9. X_sum = sum(X,2);
    10. Y_sum = sum(Y,2);
    11. Z = X_sum*Y_sum';%dxh
    12. % %This function implements the following procedure in parallel
    13. % Z = zeros(d,h);%dxh
    14. % for ii=1:m
    15. % x_i = X(:,ii);
    16. % for jj=1:q
    17. % y_j = Y(:,jj)';
    18. % Z = Z + x_i*y_j;
    19. % end
    20. % end
    21. end

            其实我真正想计算的是如下运算,里面包含一个系数:

    其中C(i,j)是一个系数,是矩阵C中的第(i,j)个元素。那么这个运算能不能并行化呢?

            使用类似的思想:

     因此,可以编写如下函数:

    1. function [ Z ] = Mtx_Coef_Col_Multi( X, Y, C )
    2. % Mtx_Coef_Col_Multi returns Z = \sum_{i=1}^{m}\sum_{j=1}^{q} C(i,j)*X(:,i)*Y(:,j)'
    3. % Here, X(:,i) and Y(:,j) denote the i-th and j-th column of X and Y, respectively
    4. % C(i,j) denotes the item in i-th row and j-th column of C.
    5. % INPUT:
    6. % X - A dxm matrix
    7. % Y - A hxq matrix
    8. % C - A mxq matrix
    9. % OUTPUT:
    10. % Z - A dxh matrix
    11. d = size(X,1);
    12. h = size(Y,1);
    13. [m,q] = size(C);
    14. if q
    15. Z = zeros(d,h);%dxh
    16. for jj=1:q
    17. y_j = Y(:,jj)';%1xh
    18. c_j = C(:,jj)';%1xm
    19. X_c = bsxfun(@times, X, c_j);%dxm
    20. X_sum = sum(X_c,2);%dx1
    21. Z = Z + X_sum*y_j;%dxh
    22. end
    23. else
    24. Z = zeros(d,h);%dxh
    25. for ii=1:m
    26. x_i = X(:,ii);%dx1
    27. c_i = C(ii,:);%1xq
    28. Y_c = bsxfun(@times, Y, c_i);%hxq
    29. Y_sum = sum(Y_c,2);%hx1
    30. Z = Z + x_i*Y_sum';%dxh
    31. end
    32. end
    33. % %This function implements the following procedure in parallel
    34. % Z = zeros(d,h);%dxh
    35. % for ii=1:m
    36. % x_i = X(:,ii);
    37. % for jj=1:q
    38. % y_j = Y(:,jj)';
    39. % Z = Z + C(ii,jj)*x_i*y_j;
    40. % end
    41. % end
    42. end

    可以使用如下代码测试一下上述并行化实现方法与串行实现的效率差异:

    1. %demo for Mtx_Coef_Col_Multi
    2. clc;clear;close;
    3. d = 5;
    4. m = 10000;
    5. h = 8;
    6. q = 50;
    7. X = rand(d,m);
    8. Y = rand(h,q);
    9. C = rand(m,q);
    10. tic;
    11. Z_serial = zeros(d,h);%dxh
    12. for ii=1:m
    13. x_i = X(:,ii);
    14. for jj=1:q
    15. y_j = Y(:,jj)';
    16. Z_serial = Z_serial + C(ii,jj)*x_i*y_j;
    17. end
    18. end
    19. toc;
    20. tic;
    21. Z = Mtx_Coef_Col_Multi(X, Y, C);
    22. toc;
    23. norm(Z_serial-Z,'fro')

    命令行窗口输出如下信息(有一定的随机性,每次运行结果有些差异):

    时间已过 1.011418 秒。

    时间已过 0.009981 秒。

    ans =

       6.5505e-09

    也就是在当前设置下,并行实现版本的效率提交了100倍左右。

  • 相关阅读:
    CDQ分治模板
    【Hadoop】关于Yarn的一些学习笔记(Hadoop权威指南读书笔记等)
    Nmap(端口扫描工具)在Windows上的安装和使用,so easy
    艾尔登法环约定之王拉塔恩打法
    深度学习 神经网络(5)逻辑回归二分类-Pytorch实现乳腺癌预测
    活动预告 | Jax Diffusers 社区冲刺线上分享(还有北京线下活动)
    Python的一个图片识别工具-PyTesseract(Win10)
    goLang sqlboiler ORM工具的使用
    未来五年,千万不要错过这波红利!
    挑战30天学完Python:Day22 爬虫
  • 原文地址:https://blog.csdn.net/jbb0523/article/details/138150647