Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何优化MATLAB逐位运算_Performance_Matlab_Integer_Bit Manipulation - Fatal编程技术网

Performance 如何优化MATLAB逐位运算

Performance 如何优化MATLAB逐位运算,performance,matlab,integer,bit-manipulation,Performance,Matlab,Integer,Bit Manipulation,我用MATLAB编写了自己的SHA1实现,它给出了正确的哈希值。但是,它非常慢(在我的核心i7-2760QM上,一个字符串a1000a需要9.9秒),我认为这种慢是因为MATLAB实现了位逻辑运算(bitand,bitor,bitxor,bitcmp)和位移位整数的(bitshift,bitrol,bitror) 我特别想知道是否需要使用fi命令为bitrol和bitror构造定点数字对象,因为不管怎样,在英特尔x86汇编中,对于所有大小的寄存器和内存地址,都有rol和ror。然而,bitshi

我用MATLAB编写了自己的SHA1实现,它给出了正确的哈希值。但是,它非常慢(在我的核心i7-2760QM上,一个字符串a1000
a
需要9.9秒),我认为这种慢是因为MATLAB实现了位逻辑运算(
bitand
bitor
bitxor
bitcmp
)和位移位整数的(
bitshift
bitrol
bitror

我特别想知道是否需要使用
fi
命令为
bitrol
bitror
构造定点数字对象,因为不管怎样,在英特尔x86汇编中,对于所有大小的寄存器和内存地址,都有
rol
ror
。然而,
bitshift
速度相当快(它不需要任何定点数字构造,常规的
uint64
变量可以正常工作),这使情况变得更加奇怪:为什么在MATLAB中
bitrol
bitror
需要使用
fi
构造定点数字对象,而
bitshift
不需要,当在汇编级时,所有这些都归结为
shl
shr
rol
ror

因此,在以.mex文件的形式在C/C++中编写此函数之前,我很高兴知道是否有任何方法可以提高此函数的性能。我知道SHA1有一些特定的优化,但这不是问题所在,如果按位旋转的基本实现非常慢的话

tic
toc
稍微测试一下,很明显,让它变慢的是
bitrol
fi
中的循环。有两个这样的循环:

%# Define some variables.
FFFFFFFF = uint64(hex2dec('FFFFFFFF'));

%# constants: K(1), K(2), K(3), K(4).
K(1) = uint64(hex2dec('5A827999'));
K(2) = uint64(hex2dec('6ED9EBA1'));
K(3) = uint64(hex2dec('8F1BBCDC'));
K(4) = uint64(hex2dec('CA62C1D6'));

W = uint64(zeros(1, 80));

... some other code here ...

%# First slow loop begins here.

for index = 17:80
    W(index) = uint64(bitrol(fi(bitxor(bitxor(bitxor(W(index-3), W(index-8)), W(index-14)), W(index-16)), 0, 32, 0), 1));
end

%# First slow loop ends here.

H = sha1_handle_block_struct.H;

A = H(1);
B = H(2);
C = H(3);
D = H(4);
E = H(5);

%# Second slow loop begins here.

for index = 1:80
    rotatedA = uint64(bitrol(fi(A, 0, 32, 0), 5));

    if (index <= 20)
        % alternative #1.
        xorPart = bitxor(D, (bitand(B, (bitxor(C, D)))));
        xorPart = bitand(xorPart, FFFFFFFF);
        temp = rotatedA + xorPart + E + W(index) + K(1);
    elseif ((index >= 21) && (index <= 40))
        % FIPS.
        xorPart = bitxor(bitxor(B, C), D);
        xorPart = bitand(xorPart, FFFFFFFF);
        temp = rotatedA + xorPart + E + W(index) + K(2);
    elseif ((index >= 41) && (index <= 60))
        % alternative #2.
        xorPart = bitor(bitand(B, C), bitand(D, bitxor(B, C)));
        xorPart = bitand(xorPart, FFFFFFFF);
        temp = rotatedA + xorPart + E + W(index) + K(3);
    elseif ((index >= 61) && (index <= 80))
        % FIPS.
        xorPart = bitxor(bitxor(B, C), D);
        xorPart = bitand(xorPart, FFFFFFFF);
        temp = rotatedA + xorPart + E + W(index) + K(4);
    else
        error('error in the code of sha1_handle_block.m!');
    end

temp = bitand(temp, FFFFFFFF);
E = D;
D = C;
C = uint64(bitrol(fi(B, 0, 32, 0), 30));
B = A;
A = temp;
end

%# Second slow loop ends here.
%#定义一些变量。
FFFFFFFF=uint64(hex2dec('ffffffffff'));
%#常数:K(1),K(2),K(3),K(4)。
K(1)=uint64(hex2dec('5A827999');
K(2)=uint64(hex2dec('6ED9EBA1');
K(3)=uint64(hex2dec('8F1BBCDC');
K(4)=uint64(hex2dec('CA62C1D6');
W=uint64(零(1,80));
…这里还有其他代码。。。
%#第一个慢循环从这里开始。
指数=17:80时
W(索引)=uint64(bitrol(fi(bitxor)(bitxor(bitxor)(W(索引-3),W(索引-8)),W(索引-14)),W(索引-16)),0,32,0),1));
结束
%#第一个慢循环到此结束。
H=sha1\U句柄\U块\U结构H;
A=H(1);
B=H(2);
C=H(3);
D=H(4);
E=H(5);
%#第二个慢循环从这里开始。
指数=1:80时
rotatedA=uint64(bitrol(fi(A,0,32,0),5));
如果(指数=21)和(指数=41)和(指数=61)和(指数
为什么在MATLAB中,bitrol和bitror需要用fi构造定点数字对象,而bitshift不需要

bitrol和bitror不是适用于UINT的位逻辑函数集的一部分。它们是定点工具箱的一部分,该工具箱还包含适用于定点输入的bitand、bitshift等变量

一个bitrol可以表示为两个位移位,一个bitand和一个bitor,如果你想尝试只使用uint函数的话。这可能会更慢。

这是来自MATLAB文件交换的,它计算SHA-1散列的速度非常快。
我运行了以下代码:

x = 'The quick brown fox jumped over the lazy dog';  %# Just a short sentence
y = repmat('a', [1, 1e6]);                           %# A million a's
opt = struct('Method', 'SHA-1', 'Format', 'HEX', 'Input', 'bin');
tic, x_hashed = DataHash(uint8(x), opt), toc
tic, y_hashed = DataHash(uint8(y), opt), toc
并得到以下结果:

x_hashed=F6513640F3045E9768B239785625CAA6A2588842

运行时间为0.029250秒。

y_hashed=34AA973CD4C4DAA4F61EEB2BDBAD27316534016F

运行时间为0.020595秒。

我用a验证了结果,计算结果确实正确。而且,106个a的散列速度比第一句快1.5倍

那么
DataHash
是如何做到如此之快的呢???使用
java.security.MessageDigest
库,同样如此!
如果您对一个快速的MATLAB友好SHA-1函数感兴趣,这是一个不错的选择


然而,如果这只是一个实现快速位级运算的练习,那么MATLAB并不能真正有效地处理它们,而且在大多数情况下,您必须求助于MEX。

因为大多数MATLAB函数,
位和
位或
位或
都是矢量化的。因此,如果将这些函数矢量化,速度会快得多r输入,而不是在每个元素上的循环中调用它们

例如:

%# create two sets of 10k random numbers
num = 10000;
hex = '0123456789ABCDEF';
A = uint64(hex2dec( hex(randi(16, [num 16])) ));
B = uint64(hex2dec( hex(randi(16, [num 16])) ));

%# compare loop vs. vectorized call
tic
C1 = zeros(size(A), class(A));
for i=1:numel(A)
    C1(i) = bitxor(A(i),B(i));
end
toc

tic
C2 = bitxor(A,B);
toc

assert(isequal(C1,C2))
时间是:

Elapsed time is 0.139034 seconds.
Elapsed time is 0.000960 seconds.
Elapsed time is 0.000984 seconds.
Elapsed time is 0.485692 seconds.
这要快一个数量级

问题是,据我所知,SHA-1计算无法很好地矢量化,因此您可能无法利用这种矢量化

作为一个实验,我实现了一个纯基于MATLAB的函数来计算这样的位运算:

function num = my_bitops(op,A,B)
    %# operation to perform: not, and, or, xor
    if ischar(op)
        op = str2func(op);
    end

    %# integer class: uint8, uint16, uint32, uint64
    clss = class(A);
    depth = str2double(clss(5:end));

    %# bit exponents
    e = 2.^(depth-1:-1:0);

    %# convert to binary
    b1 = logical(dec2bin(A,depth)-'0');
    if nargin == 3
        b2 = logical(dec2bin(B,depth)-'0');
    end

    %# perform binary operation
    if nargin < 3
        num = op(b1);
    else
        num = op(b1,b2);
    end

    %# convert back to integer
    num = sum(bsxfun(@times, cast(num,clss), cast(e,clss)), 2, 'native');
end
时间是:

Elapsed time is 0.139034 seconds.
Elapsed time is 0.000960 seconds.
Elapsed time is 0.000984 seconds.
Elapsed time is 0.485692 seconds.

结论:编写一个MEX函数或搜索文件交换,看看是否有人已经这样做了:)

通过替换所有my
bitrol(fi(…
使用我自己的向左旋转函数的代码1000的计算时间从9.9秒减少到0.42秒左右,因此现在比以前快了23.5倍。但是,计算较长消息的SHA1哈希(例如,FIPS文档中的100万(10^6)示例消息)
a
仍然需要大约422秒(我的原始代码需要9430秒来计算),而运行
time printf'a%.0s'{1..1000000}bash中的| sha1sum
只需要0.953秒。因此,比我原来的速度快23.5倍,但仍然比
sha1sum
慢约440倍。在我看来,加速SHA1的选项是使用
java.security.MessageDigest
库或编写一个MEX函数。因为我正计划使我的MATLAB代码与GNU Octav兼容e(也希望使用GNUOctave作为开发环境),而且似乎MATLAB和Octave在处理Java方面存在一些差异,使用Java库是一个不理想的解决方案。然而,
DataHash
速度非常快,因此,在我实现MEX解决方案或找到另一种高效实现SHA1的方法之前,它将完成这项工作,而不使用Javawn功能磁共振成像a