Erlang实现的矩阵相乘C=A*B单线程与并行多线程性能对比

来源:互联网 发布:淘宝家装基金是什么 编辑:程序博客网 时间:2024/05/18 02:08

-module(new).
-export([]).
-compile(export_all).
%% ====================================================================
%% Internal functions
%% ====================================================================
%%测试入口
test() ->
 A = generateMatrix(50,300),
 B = generateMatrix(300,30),
 {Time,Value} = timer:tc(new,matrixMultiply,[A,B]),
 io:format("Single Thread:~p[ms]~n",[Time/1000]),
 {Time1,Value1} = timer:tc(new,multiThread,[A,B]),
 io:format("Multi Thread:~p[ms]~n",[Time1/1000]).
 %% 随机产生M*N矩阵
generateMatrix(M,N) ->
    row(M,N,[]).
row(M,N,Result) ->
 case 0 =:= M of
  true -> Result;
  false -> row(M-1,N,Result++[column(N,[])])
 end.
column(N,Result) ->
 case 0 =:= N of
  true -> Result;
  false -> column(N-1,Result++[random:uniform(1000)])
 end.
%% 单线程
matrixMultiply(A,B) ->
 R = lists:foldl(fun(Element,Acc) -> Acc++[rowMultiplyColumn(Element,B,[],1)] end, [], A),
 io:format("~w~n",[R]).
%% 多线程
multiThread(A,B) ->
 P = self(),
%%  启动矩阵A的行数个进程,分别发送A的每一行,计算A的每一行与矩阵B的乘积
 lists:foldl(fun(Element,Acc) -> spawn(fun() -> P! {self(),Acc,rowMultiplyColumn(Element,B,[],1)} end)  end, 1, A),
%% 接收,当前进程如果收到了A行数个消息,表明已经计算完毕
   loop(length(A)).
%% 统计当前进程是否已经收到了Count条消息
   loop(Count) ->
  receive
    {Pid,N,Result} ->
%%      io:format("Count=~p,Message=~w~n",[Count,{Pid,N,Result}]),
     case 1=:= Count of
      true -> io:format("Compute end~n");
      false -> loop(Count-1)
     end
  end.
%%@author zcc
%%@date   2014-04-16
%%@param A,B:list;Result:存放结果,初始为[];Count:控制列数,初始为1;Result:存放结果,初始为[]  
%%将某一行A与矩阵B相乘,得出一组向量
rowMultiplyColumn(A,B,Result,Count) ->
  case Count =:= length(lists:nth(1,B))+1 of
   true -> Result;
   false ->
        rowMultiplyColumn(A,B,Result ++ [multiply(A,getMatrixColumn(B,Count),0)],Count+1)
  end.
%% 得到矩阵B的第Num列
getMatrixColumn(B,Num) ->
 lists:foldl(fun(A,Acc) -> Acc++[lists:nth(Num, A)] end, [],B).
%% 计算两个向量List的数量积
multiply([H1|T1],[H2|T2],Sum)  when length(T1) =:= length(T2)  ->
 multiply(T1,T2,Sum+H1*H2);
multiply([],[],Sum) -> Sum.

%% 计算两个向量积的另一种方法
%% multiplyAndSum(A,B,Result,Count) when length(A) =:= length(B) ->
%%  case 0 =:= Count of
%%   true -> Result;
%%   false ->
%%    Sum = Result ++ lists:nth(Count,A)*lists:nth(Count, B),
%%    multiplyAndSum(A,B,Sum,Count-1)
%%  end.
%% 总结:(1)erlang多进程的消息交互
%%      (2)如何统计erlang进程邮箱中接收到消息的数量,本例中的loop方法
%%      (3)erlang递归计数问题词的训练

1 0
原创粉丝点击