主要内容

在收缩阵列中使用CORDIC实现硬件高效的QR分解

这个例子展示了如何在Simulink®中使用硬件高效的MATLAB®代码计算矩阵的QR分解。金宝app

要求解方程组或使用QR分解计算矩阵方程AX = B的最小二乘解,请计算R和Q'B,其中QR = a, RX = Q'B。R是一个上三角矩阵Q是一个正交矩阵。如果你只想要Q和R,那么让B是单位矩阵。

在这个例子中,R是通过使用CORDIC算法应用Givens变换从矩阵A计算出来的。C = Q'B通过应用相同的Givens变换从矩阵B计算出来。该算法只使用迭代移位和加法来执行这些计算。

有关此示例中使用的算法的更多信息,请参见使用CORDIC执行QR分解

概述

本例中使金宝app用的Simulink模型为:

fxpdemo_real_4x4_systolic_array_QR_model

要输入您自己的输入矩阵A和B,请打开左侧相应启用的子系统块的块参数。仿真完成后,模型将计算出的输出矩阵C = Q'B和R返回给工作空间。您可以在转置(Q)*B, R 4x4 Real CORDIC Systolic Array子系统的块参数中指定CORDIC迭代的次数。如果输入是固定的点,那么CORDIC迭代的次数必须小于单词长度。每次迭代计算的精度提高一位,直到输入的字长。

此模型可用于定点数据类型、双数据类型和单数据类型。

要了解算法如何执行因式分解,请查看转置(Q)*B, R 4x4 Real CORDIC收缩阵列子系统的掩码。注释指出正在对矩阵的哪些行进行操作,以将次对角线元素归零。收缩阵列是为4 × 4矩阵a设置的,但可以通过遵循相同的模式扩展到任何大小。此实现仅适用于实际输入矩阵。

要查看使用CORDIC执行Givens转换的MATLAB函数块中的MATLAB代码,请继续查看块掩码下面的内容。

在本例中,A的行数和列数必须为4。矩阵B必须有4行和任意数量的列。

用QR法求解矩阵方程Ax = B

求解矩阵方程AX = B的第一步是计算RX = Q'B,其中R是上三角,Q是正交的,Q*R = A。

以下输入是双精度浮点类型,因此将迭代次数设置为52,这是double尾数中的位数。

格式NumberOfCORDICIterations = 52;A = 2*rand(4,4)-1;B = 2*rand(4,4)-1;

模拟模型计算R和C = Q'B。

sim卡fxpdemo_real_4x4_systolic_array_QR_modelR C
R = 1.5149 -0.0519 1.7292 -0.3224 0 0.9593 -0.0259 -0.0879 0 0 0.2565 1.0888 0 0 0 0 -0.6429 c = 0.5942 -0.2382 0.0676 -0.9370 -0.8887 0.6146 -0.5758 0.3051 0.1725 0.7339 0.5409 0.5374 0.8540 1.1078 -0.2183 -0.5620

验证用R和C = Q'B进行反向替换得到的结果与MATLAB相同。

X = R\C x_d_be = A\B
X = -7.1245 -12.1131 -0.6637 1.4236 -0.8779 0.7572 -0.5511 0.3545 6.3113 -1.6155 -1.3283 -1.7231 0.3396 0.8741 X_should_be = -7.1245 -12.1131 -0.6637 1.4236 -0.8779 0.7572 -0.5511 0.3545 6.3113 10.1759 0.6673 -1.6155 -1.3283 -1.7231 0.3396 0.8741

内置MATLAB与CORDIC QR解之间的差异范数应该很小。

范数(X - X_should_be)
Ans = 2.6739e-14

计算Q和R

要计算Q和R,令B等于单位矩阵。当B等于单位矩阵时,Q = C'

NumberOfCORDICIterations = 52;A = 2*rand(4,4)-1;B =眼睛(大小(A,1),“喜欢”,);sim卡fxpdemo_real_4x4_systolic_array_QR_modelQ = c ';

理论QR分解为QR==A,因此计算QR与A的差值应该很小。

范数(Q*R - A)
Ans = 2.2861e-15

QR不是唯一的

QR分解只有在R的行和q的列的符号处是唯一的你可以通过使R的对角线元素都为正来做一个唯一的QR分解。

D = diag(符号(diag(R)));Qunique = Q*D Runique = D*R
Qunique = -0.3086 0.1224 -0.1033 -0.9376 -0.6277 -0.7636 -0.0952 0.1174 -0.5573 0.3930 0.7146 0.1559 0.4474 -0.4975 0.6852 -0.2877 Runique = 1.4459 -0.8090 0.1547 0.3977 0 1.1441 0.0809 -0.2494 0 0 0.8193 0.1894 0 0 0 0 0.4836

然后,您可以比较从模型计算出的QR与内置的MATLAB QR函数。

[Q0,R0] = qr(A);D0 = diag(符号(diag(R0)));Q0 = Q0* d0 r0 = d0 * r0
Q0 = -0.3086 0.1224 -0.1033 -0.9376 -0.6277 -0.7636 -0.0952 0.1174 -0.5573 0.3930 0.7146 0.1559 0.4474 -0.4975 0.6852 -0.2877 r0 = 1.4459 -0.8090 0.1547 0.3977 0 1.1441 0.0809 -0.2494 0 0 0.8193 0.1894 0 0 0 0 0.4836

使用定点硬件高效实现

使用定点输入数据类型为ASIC和FPGA设备生成高效的HDL代码。

有关如何选择不会溢出的定点数据类型的详细信息,请参阅示例使用CORDIC执行QR分解

通过创建A和B 3维数组,您可以通过模型运行许多测试输入。

n_test_inputs = 100;

下一节定义了矩阵A和B的随机输入,它们在-1到1之间缩放,因此将定点字长度设置为18位,将分数长度设置为14位,以允许CORDIC算法中的QR分解和中间计算的增长。

Word_length = 18;Fraction_length = 14;

CORDIC迭代的最佳精度数是单词长度减1。如果CORDIC迭代的次数设置为小于word_length - 1,那么到下一个就绪信号的延迟和时钟滴答将会更短,但它将不那么准确。CORDIC迭代的次数不应该设置得更大,因为生成的代码不支持大于定点类型字长的移位。金宝app

NumberOfCORDICIterations = word_length - 1
NumberOfCORDICIterations = 17

随机测试输入被连接起来,因此在时间k时,输入是A(:,:,k)和B(:,:,k)。A和B中的每个元素都是一个在-1到+1之间的均匀随机变量。

A = 2*rand(4,4,n_test_inputs)-1;

选B为单位矩阵Q=C'

B =眼睛(4);B = repmat(B,1,1,n_test_inputs);

将A施放到固定点,并像A一样施放B。

A = fi(A,1,word_length,fraction_length);B = cast(B,“喜欢”,);

模拟模型

sim卡fxpdemo_real_4x4_systolic_array_QR_model

计算并绘制误差图

norm_error = 0 (1,size(R,3));k = 1:尺寸(R, 3) Q_times_R_minus_A =双(C (:,:, k))的*双(R (:,:, k)) -双((:,:,k));norm_error(k) = norm(Q_times_R_minus_A);结束

误差应该在10^ 3的数量级上。

clf情节(norm_error“啊——”网格)标题(norm(QR - A)

% #好< * NASGU, * NOPTS >