高效读取输入文件
Efficient Reading of Input File
目前,我正在处理一个任务,输入文件提供与矩阵相关的测试用例(矩阵乘法),即输入文件示例 ->
N M
1 3 5 ... 6 (M columns)
....
5 4 2 ... 1 (N rows)
到目前为止,我一直使用简单的 read() 来访问它们,但这对于大小 > 10^2 的大文件来说效率不高。
所以我想知道是否有某种方法可以使用进程并行执行此操作。
我也在考虑使用基于行的多个 IO 读取器,这样每个进程都可以读取文件的不同部分,但找不到任何有用的资源。
谢谢。
PS:当前代码使用的是:
io:fread(IoDev, "", "~d")
is there some way to use processes to do this in parallel.
当然可以。
Also I was thinking of using multiple IO readers based on line, so
then each process could read different segments of the file but
couldn't find any helpful resources.
您不是按行查找文件中的位置,而是按字节查找位置。虽然文件可能看起来像一堆行,但文件实际上只是一长串字符。因此,您需要确定要在文件中查找的字节位置。
查看 file:position, file:pread。
您是否考虑过使用 re
模块?我没有做性能测试,但它可能是高效的。在下面的示例中,我不使用第一个“M N”行。所以我没有把它放在matrix.txt文件中。
矩阵文件:
1 2 3 4 5 6 7 8 9
11 12 13 14 15 16 17 18 19
21 22 23 24 25 26 27 28 29
31 32 33 34 35 36 37 38 39
我在 shell
中进行了转换
1> {ok,B} = file:read_file("matrix.txt"). % read the complete file and store it in a binary
{ok,<<"1 2 3 4 5 6 7 8 9\r\n11 12 13 14 15 16 17 18 19\r\n21 22 23 24 25 26 27 28 29\r\n31 32 33 34 35 36 37 38 39">>}
2> {ok,ML} = re:compile("[\r\n]+"). % to split the complete binary in a list a binary, one for each line
{ok,{re_pattern,0,0,0,
<<69,82,67,80,105,0,0,0,0,0,0,0,1,8,0,0,255,255,255,255,
255,255,...>>}}
3> {ok,MN} = re:compile("[ ]+"). % to split the line into binaries one for each integer
{ok,{re_pattern,0,0,0,
<<69,82,67,80,73,0,0,0,0,0,0,0,17,0,0,0,255,255,255,255,
255,255,...>>}}
4> % a function to split a line and convert each chunk into integer
4> F = fun(Line) -> Nums = re:split(Line,MN), [binary_to_integer(N) || N <- Nums] end.
#Fun<erl_eval.7.126501267>
5> Lines = re:split(B,ML). % split the file into lines
[<<"1 2 3 4 5 6 7 8 9">>,<<"11 12 13 14 15 16 17 18 19">>,
<<"21 22 23 24 25 26 27 28 29">>,
<<"31 32 33 34 35 36 37 38 39">>]
6> lists:map(F,Lines). % map the function to each lines
[[1,2,3,4,5,6,7,8,9],
[11,12,13,14,15,16,17,18,19],
[21,22,23,24,25,26,27,28,29],
[31,32,33,34,35,36,37,38,39]]
7>
如果要检查矩阵大小,可以将最后一行替换为:
[[NbRows,NbCols]|Matrix] = lists:map(F,Lines),
case (length(Matrix) == NbRows) andalso
lists:foldl(fun(X,Acc) -> Acc andalso (length(X) == NbCols) end,true,Matrix) of
true -> {ok,Matrix};
_ -> {error_size,Matrix}
end.
目前,我正在处理一个任务,输入文件提供与矩阵相关的测试用例(矩阵乘法),即输入文件示例 ->
N M
1 3 5 ... 6 (M columns)
....
5 4 2 ... 1 (N rows)
到目前为止,我一直使用简单的 read() 来访问它们,但这对于大小 > 10^2 的大文件来说效率不高。
所以我想知道是否有某种方法可以使用进程并行执行此操作。
我也在考虑使用基于行的多个 IO 读取器,这样每个进程都可以读取文件的不同部分,但找不到任何有用的资源。
谢谢。
PS:当前代码使用的是:
io:fread(IoDev, "", "~d")
is there some way to use processes to do this in parallel.
当然可以。
Also I was thinking of using multiple IO readers based on line, so then each process could read different segments of the file but couldn't find any helpful resources.
您不是按行查找文件中的位置,而是按字节查找位置。虽然文件可能看起来像一堆行,但文件实际上只是一长串字符。因此,您需要确定要在文件中查找的字节位置。
查看 file:position, file:pread。
您是否考虑过使用 re
模块?我没有做性能测试,但它可能是高效的。在下面的示例中,我不使用第一个“M N”行。所以我没有把它放在matrix.txt文件中。
矩阵文件:
1 2 3 4 5 6 7 8 9
11 12 13 14 15 16 17 18 19
21 22 23 24 25 26 27 28 29
31 32 33 34 35 36 37 38 39
我在 shell
中进行了转换1> {ok,B} = file:read_file("matrix.txt"). % read the complete file and store it in a binary
{ok,<<"1 2 3 4 5 6 7 8 9\r\n11 12 13 14 15 16 17 18 19\r\n21 22 23 24 25 26 27 28 29\r\n31 32 33 34 35 36 37 38 39">>}
2> {ok,ML} = re:compile("[\r\n]+"). % to split the complete binary in a list a binary, one for each line
{ok,{re_pattern,0,0,0,
<<69,82,67,80,105,0,0,0,0,0,0,0,1,8,0,0,255,255,255,255,
255,255,...>>}}
3> {ok,MN} = re:compile("[ ]+"). % to split the line into binaries one for each integer
{ok,{re_pattern,0,0,0,
<<69,82,67,80,73,0,0,0,0,0,0,0,17,0,0,0,255,255,255,255,
255,255,...>>}}
4> % a function to split a line and convert each chunk into integer
4> F = fun(Line) -> Nums = re:split(Line,MN), [binary_to_integer(N) || N <- Nums] end.
#Fun<erl_eval.7.126501267>
5> Lines = re:split(B,ML). % split the file into lines
[<<"1 2 3 4 5 6 7 8 9">>,<<"11 12 13 14 15 16 17 18 19">>,
<<"21 22 23 24 25 26 27 28 29">>,
<<"31 32 33 34 35 36 37 38 39">>]
6> lists:map(F,Lines). % map the function to each lines
[[1,2,3,4,5,6,7,8,9],
[11,12,13,14,15,16,17,18,19],
[21,22,23,24,25,26,27,28,29],
[31,32,33,34,35,36,37,38,39]]
7>
如果要检查矩阵大小,可以将最后一行替换为:
[[NbRows,NbCols]|Matrix] = lists:map(F,Lines),
case (length(Matrix) == NbRows) andalso
lists:foldl(fun(X,Acc) -> Acc andalso (length(X) == NbCols) end,true,Matrix) of
true -> {ok,Matrix};
_ -> {error_size,Matrix}
end.