Ik moet voor een project een systeem van lineaire vergelijkingen met 5 onbekenden oplossen. Geschreven in matrices levert dit systeem een vergelijking op in de vorm A * x = B, waarbij A een 5x5 matrix en B een 5x1 matrix is, de onbekenden staan in de 5x1 matrix x. Een dergelijk systeem kan o.a. opgelost worden met Gaussian of Gauss-Jordan eliminatie.
Matrix A wordt opgestelt uit 5 paar data samples uit een AD converter. De samples worden vooraf gecontroleerd op afhankelijkheid. Als de samples niet afhankelijk zijn, en de matrix vergelijking dus oplosbaar is, wordt de matrix opgesteld en de berekening uitgevoerd door een TMS320C6713 floating-point DSP van TI. De uitkomst van de matrix moet berekend zijn voordat de volgende samples door de AD converter aangeleverd worden en de rekentijd voor het oplossen van de matrix moet tot een minimum beperkt worden.
Volgens verschillende bronnen op internet (o.a. PlanetMath) zou een implementatie van gaussian eliminatie sneller zijn. Om dit te testen heb ik 2 functies geschreven om de executietijd te kunnen vergelijken. Bij beide implementaties is SamplesMatrix een 5x6 array, waarbij matrix A in de eerste 5 kolommen staat en matrix B in de laatste kolom. Na afloop van de functie staan in de laatste kolom de antwoorden van de 5 onbekenden.
Tegen verwachting in is de exectutietijd van de PerformGaussJordan functie korter (11843 klokcyles op de c6713) dan PerformGaussian functie (13717 klokcycles op de c6713). Waarschijnlijk zullen de geneste for-loops bij de Gaussian eliminatie voor veel vertraging zorgen, echter ik kan zelf geen oplossing bedenken waar deze for-loops, of een andere vorm van loop, niet nodig zijn.
Ziet een van jullie waar de performence van de Gaussian eliminatie verbeterd kan worden? Deze implementatie zou namelijk sneller moeten zijn. Als jullie nog verbeterpunten zien in de PerformGaussJordan functie of misschien een heel ander algoritme weten dan hoor ik dit ook erg graag, de huidige 11843 klokcycles is namelijk nog veel te veel!
Matrix A wordt opgestelt uit 5 paar data samples uit een AD converter. De samples worden vooraf gecontroleerd op afhankelijkheid. Als de samples niet afhankelijk zijn, en de matrix vergelijking dus oplosbaar is, wordt de matrix opgesteld en de berekening uitgevoerd door een TMS320C6713 floating-point DSP van TI. De uitkomst van de matrix moet berekend zijn voordat de volgende samples door de AD converter aangeleverd worden en de rekentijd voor het oplossen van de matrix moet tot een minimum beperkt worden.
Volgens verschillende bronnen op internet (o.a. PlanetMath) zou een implementatie van gaussian eliminatie sneller zijn. Om dit te testen heb ik 2 functies geschreven om de executietijd te kunnen vergelijken. Bij beide implementaties is SamplesMatrix een 5x6 array, waarbij matrix A in de eerste 5 kolommen staat en matrix B in de laatste kolom. Na afloop van de functie staan in de laatste kolom de antwoorden van de 5 onbekenden.
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| void PerformGaussian (float (*SamplesMatrix)[6]) { float Temp; // Walk through columns for (INT8 i = 0; i < 5; i++) { // Walk through rows beneath working row number for (INT8 j = i + 1; j < 5; j++) { // Walk through current column and those on the right it for (INT8 k = 5; k >= i; k--) { SamplesMatrix[j][k] -= SamplesMatrix[i][k] * (SamplesMatrix[j][i] / SamplesMatrix[i][i]); } } } // Back substitution for (INT8 j = 4; j >= 0; j--) { Temp = 0; for (INT8 k = j + 1; k < 5; k++) { Temp += SamplesMatrix[j][k] * SamplesMatrix[k][5]; } SamplesMatrix[j][5] = (SamplesMatrix[j][5] - Temp) / SamplesMatrix[j][j]; } } |
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| void PerformGaussJordan (float (*SamplesMatrix)[6]) { float Calculator; // Walk through the rows of the matrix for (INT8 i = 0; i < 5; i++) { // Store working point value Calculator = SamplesMatrix[i][i]; // Walk through columns in current row for (INT8 j = 0; j < 6; j++) { // Divide sample value by working point value. // Results in a 1 in the working point. SamplesMatrix[i][j] /= Calculator; } // Walk through the rows of the matrix... for (INT8 j = 0; j < 5; j++) { // ...except the current row if (j != i) { // Store value in working row working point column Calculator = SamplesMatrix[j][i]; // Walk through columns in working row for (INT8 k = 0; k < 6; k++) { SamplesMatrix[j][k] -= Calculator * SamplesMatrix[i][k]; } } } } } |
Tegen verwachting in is de exectutietijd van de PerformGaussJordan functie korter (11843 klokcyles op de c6713) dan PerformGaussian functie (13717 klokcycles op de c6713). Waarschijnlijk zullen de geneste for-loops bij de Gaussian eliminatie voor veel vertraging zorgen, echter ik kan zelf geen oplossing bedenken waar deze for-loops, of een andere vorm van loop, niet nodig zijn.
Ziet een van jullie waar de performence van de Gaussian eliminatie verbeterd kan worden? Deze implementatie zou namelijk sneller moeten zijn. Als jullie nog verbeterpunten zien in de PerformGaussJordan functie of misschien een heel ander algoritme weten dan hoor ik dit ook erg graag, de huidige 11843 klokcycles is namelijk nog veel te veel!