實例來自於《CCSDS標準的LDPC編譯碼仿真》中代碼(實際上有點點差異),代碼優化從如下幾個方面進行
稀疏 仿真中的第一個困難在於ccsdscheckmatrix函數在輸入SIZE_M很大的時候,先不說運行時間,直接就爆內存了。(輸入參數4096,2/3) 先分析分析內存的問題,實際上這個函數的最後輸出結果就是一個矩陣,這個矩陣的大小是12288×28672,計算double型的內存佔用也就2G左右。可是函數運行過程當中產生了不少中間變量沒有清除。固然最後的解決辦法也沒有去管這些東西,因爲矩陣H是稀疏矩陣,因此之際採用sparse後,這個運行就沒有任何問題了。 對於矩陣H和H_sparse = spares(H),佔用內存以下(固然H要是稀疏的,否則得不償失) Name Size Bytes Class Attributes H 12288x28672 2818572288 double H_sparse 12288x28672 1736712 double sparse 也能夠對比稀疏矩陣和原始矩陣的運行時間(和稀疏程度有關) 代碼:tic;H*message';toc; 結果:時間已過 0.288934 秒。 代碼:tic;H_sparse*message';toc; 結果:時間已過 0.001210 秒。 類型轉換 MATLAB中的運算符支持多種類型,譬如矩陣乘法中多用double型變量,但若是一個矩陣是邏輯輸入也沒有關係。但運算速度差別較大,譬如 >> Gc_logic = Gc>0; >> a=randi([0 1],1,16384); >> tic;b = a*Gc;toc 時間已過 0.107618 秒。 >> tic;b = a*Gc_logic;toc 時間已過 0.503132 秒。 觀測結果類型爲double,咱們能夠大膽推測實際上邏輯型變量在運算過程當中先轉化爲了double型(邏輯怎麼乘呢?)另外一個實驗結果是 >> tic;Gc_logic=double(Gc_logic);b = a*Gc_logic;toc 時間已過 0.546412 秒。 這必定程度上證實了咱們的假設。因此在運算過程當中數據類型是重要的,若是上述乘法出如今循環內,那麼實現轉化矩陣類型是必要的。即便只運行一次,那麼顯式的轉化矩陣類型(特製新建變量)也有好處。譬如 >> tic;Gt=double(Gc_logic);b = a*Gt;toc 時間已過 0.373506 秒。 經過建立新變量,運行速度些許。 向量化 向量化其實是原代碼修改中獲益最大的方法,這其實是由於原先的譯碼程序寫了太多的循環。向量化後運行時間變成了原先的1/40 。固然,原先的代碼通用性強,而向量化這個過程其實是運用了H的一些結構的。譯碼函數太複雜,此處不作舉例。 此處分析差分調製中的例子(實際上對這個程序沒有什麼影響) 原來的代碼是這個樣子的(更新值爲其自己和前一個值的異或) encodeData_extend = [1 encodeData]; for num = 2:length(encodeData_extend) encodeData_extend(num) = xor(encodeData_extend(num),encodeData_extend(num-1)); end 向量化的結果爲(累加模二代替異或) encodeData1 = [1 encodeData]; encodeData1_sum = cumsum(encodeData1); encodeData_2 = mod(encodeData1_sum,2); 運行時間分別爲 時間已過 0.023424 秒。 時間已過 0.015003 秒。 雖而後者沒有快不少,但這取決於向量的長度,長度大的話會有較大差距。 其餘 MATLAB中說起的都能對代碼運行速度帶來細微的改進,包括
-
將長腳本拆開成小段,調用執行;
-
將大的代碼塊分開爲獨立的函數;
-
將過度複雜的函數或是表達式採用簡單的來代替;
-
採用函數,而不是腳本;
上述測試腳本(和以上運行條件有差異)
%% 稀疏矩陣測試
M=4096;
theta=[1 1 2 3 1 1 2 3 1 2 3 0 2 3 0 2 3 0 1 3 0 1 3 0 1 2];
fai=[1787 1077 1753 697 1523 5 2035 331 1920 130 4 85 551 15 1780 1960 3 145 1019 691 132 42 393 502 201 1064
1502 602 749 1662 1371 9 131 1884 1268 1784 19 1839 81 2031 76 336 529 74 68 186 905 1751 1516 1285 1597 1712
1887 521 590 1775 1738 2032 2047 85 1572 78 26 298 1177 1950 1806 128 1855 129 269 1614 1467 1533 925 1886 2046 1167
1291 301 1353 1405 997 2032 11 1995 623 73 1839 2003 2019 1841 167 1087 2032 388 1385 885 707 1272 7 1534 1965 588];
A = zeros(M);
B = eye(M);
L = 0:M-1;
for matrixNum = 1:14
t_k = theta(matrixNum);
f_4i_M = floor(4*L/M);
f_k = fai(f_4i_M+1,matrixNum)';
col_1 = M/4*(mod((t_k+f_4i_M),4)) + ...
mod((f_k+L),M/4);
row_col = col_1+1 + L*M;
C_temp = zeros(M);
C_temp(ind2sub([M,M],row_col)) = 1;
C{matrixNum} = sparse(C_temp)';
end
H = [A A A B B+C{1};B+C{8} B+C{7}+C{6} A A B;A B B+C{5} A C{4}+C{3}+C{2}];
H_23 = [A A;B C{11}+C{10}+C{9};C{14}+C{13}+C{12} B];
H=[H_23 H];
H_full = full(H);
whos H H_full
%% 稀疏矩陣乘法測試
message = randi([0 1],1,28672);
tic;H*message';toc;
tic;H_full*message';toc;
%% 數據類型測試
Gc = randn(16384);
Gc_logic = Gc>0;
a=randi([0 1],1,16384);
tic;b = a*Gc;toc
tic;b = a*Gc_logic;toc %邏輯型運行花費時間
tic;Gc_logic=double(Gc_logic);b = a*Gc_logic;toc %類型轉換
tic;Gt=double(Gc_logic);b = a*Gt;toc %創建新變量
%% 向量化測試
encodeData = randi([0 1],1,1000000);
tic;
encodeData_extend = [1 encodeData];
for num = 2:length(encodeData_extend)
encodeData_extend(num) = xor(encodeData_extend(num),encodeData_extend(num-1));
end
toc;
tic;
encodeData1 = [1 encodeData];
encodeData1_sum = cumsum(encodeData1);
encodeData_2 = mod(encodeData1_sum,2);
toc;
View Code
|