Erlang实现的矩阵相乘C=A*B单线程与并行多线程性能对比
2014-04-16 21:12
483 查看
-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递归计数问题词的训练
-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递归计数问题词的训练
相关文章推荐
- jxls jx:forEach 中嵌套jx:if 再就sum时 报错
- 【LeetCode练习题】Valid Palindrome
- 倒排文件索引
- 查看及管理Oracle patch
- linux配置选项详解
- 大数运算-除法-Octal Fractions
- 图像处理的傅里叶变换
- Linux平台下利用JNI+双向RMI实现远程推送
- 常见开源协议名词解释
- 转载:Mac 电脑如何安装mac os 和win7双系统(win7多分区)
- ABAP可以提高效率的小语法
- 20140416 triangle
- nyoj-37 回文字符串
- TYVJ 1049 最长不下降子序列
- Sizeof与Strlen的区别与联系
- 常用开源协议BSD/APACHE/GPL/LGPL/CPL/MIT概述
- C#使用Zebra 斑马打印标签--使用winspool.Drv方式
- SharedObject.getLocal("application-name")
- C# 操作FTP
- python处理html中的转义字符