Matrisberäkningar med för STM32?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av Al_Bundy »

Alltså kan jag skriva en C-kod så här. Som ni ser så är endast matrix* a och matrix* b dynamiskt allokerade, men alla andra matriser så som float x[n], vectorI[n] osv är lokala "matriser och vektorer" är inte skapade via malloc. Detta är alltså OK om jag gör så här?

Innan så hade inv() kommandot olika anrop med dynamiska matriser som sedan frigjordes. Det var detta som många var kritiska till, att man använder malloc och free i t.ex. en for-loop.

Kod: Markera allt

void inv(matrix* a, matrix* b) {

	/*
	 * This uses LU decomposation to find the inverse of matrix a
	 */

	int n = a->row;
	float vectorI[n];
	float x[n];
	memset(x, 0, sizeof(x)); // reset
	float* ptr_out = b->data;

	for (int i = 0; i < n; i++) {
		// Create one column identity "matrix"
		vectorI[i] = 1;

		// Solve
		linsolve_internal_inv(a, vectorI, x);

		// Insert
		for (int j = 0; j < n; j++)
			*((ptr_out + j * n) + i) = x[j];


		// Reset
		memset(vectorI, 0, sizeof(vectorI));
		memset(x, 0, sizeof(x));

	}

}


/*
 * This is internal linear solving procedure for just this inv-command.
 */
void linsolve_internal_inv(matrix*a, float* b, float* c) {

	/*
	 * This uses LU-factorization to solve Ax = b equation
	 */

	// Get data for matrix a
	int n = a->row;
	int m_a = a->column;

	// Do LU-factorization
	float l[n*m_a];
	float u[n*m_a];
	lu_internal_inv(a, l, u);

	// Initial sum
	float sum = 0;
	float y[n*m_a]; // Vector
	///float* ptr_x = c->data; // our output

	// Solve Ly = b with gaussian elimination
	for (int i = 0; i < n; i++) {
		sum = 0;
		for (int j = 0; j < i; j++)
			sum += *((l + i * n) + j) * (*(y + j));
		*(y + i) = (*(b + i) - sum) / (*((l + i * n) + i));
	}

	// Solve Ux = y with gaussian elimination
	for (int i = n-1; i >= 0; i--) {
		sum = 0;
		for (int j = i; j < n; j++)
			sum += *((u + i * n) + j) * (*(c + j));
		*(c + i) = (*(y + i) - sum) / (*((u + i * n) + i));
	}

}

/*
 * This is LU-factorization for internal for just this inv-command.
 */
void lu_internal_inv(matrix* a, float* l, float* u) {
	// Get info about matrix 'a'
	int n = a->row;
	int m = a->column;
	float* ptr_a = a->data;

	float sum = 0;

	// Initial values for matrix u and l
	memset(u, 1, m * n * sizeof(float));
	memset(l, 0, m * n * sizeof(float));


	for (int j = 0; j < n; j++) {
		for (int i = j; i < n; i++) {
			sum = 0;
			for (int k = 0; k < j; k++) {
				sum = sum + *((l + i*n) + k) * (*((u + k*n) + j));
			}
			*((l + i*n) + j) = *((ptr_a + i*n) + j) - sum;
		}

		for (int i = j; i < n; i++) {
			sum = 0;
			for (int k = 0; k < j; k++) {
				sum = sum + *((l + j*n) + k) * (*((u + k*n) + i));
			}
			if (*((l + j*n) + j) == 0) {
				printf("det(L) close to 0!\n Can't divide by 0...\n");
				*((l + j*n) + j) = pow(2.2204, -16); // Same as eps command in MATLAB
			}
			*((u + j*n) + i) = (*((ptr_a + j*n) + i) - sum) / (*((l + j*n) + j));
		}
	}
}


Rick81
Inlägg: 755
Blev medlem: 30 december 2005, 13:07:09

Re: Matrisberäkningar med för STM32?

Inlägg av Rick81 »

Osäker på om alla kompilatorer fixar denna
int n = a->row;
   float vectorI[n];

Detta är ju en dynamisk array. Normalt definerar man dessa storlekarmed defines.Borde väl vara MAX_MATRIX_SIZE eller nåt.

Varför nollar du arrayer som inte används nåt mer? Slösar bara instruktioner.

      // Reset
      memset(vectorI, 0, sizeof(vectorI));
      memset(x, 0, sizeof(x));
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: Matrisberäkningar med för STM32?

Inlägg av snigelen »

> Osäker på om alla kompilatorer fixar denna

Det ingår i C99-standarden (variable length array).
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av Al_Bundy »

Rick81 skrev:Osäker på om alla kompilatorer fixar denna
int n = a->row;
float vectorI[n];

Detta är ju en dynamisk array. Normalt definerar man dessa storlekarmed defines.Borde väl vara MAX_MATRIX_SIZE eller nåt.

Varför nollar du arrayer som inte används nåt mer? Slösar bara instruktioner.

// Reset
memset(vectorI, 0, sizeof(vectorI));
memset(x, 0, sizeof(x));
Ingår i C99.

Så noga är det inte.

Men är det OK att man gör så här? Arrayer i inbyggda system för funktioner.
Rick81
Inlägg: 755
Blev medlem: 30 december 2005, 13:07:09

Re: Matrisberäkningar med för STM32?

Inlägg av Rick81 »

Ja det är ok. Bara man tänker på hur mycket stack man definerat. Men några hundra byte ska inte vara några problem för en STM32
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av Al_Bundy »

Jag har koll på minnet. Men var det inte detta som var ett problem enligt ni?

När jag deklarerar en array så lägga det på stacken. Samma sak när jag deklarerar med malloc? Vad är skillnaden?

Jag vet om att med malloc så raderas inte just det jag allokerade automatiskt.
bearing
Inlägg: 11653
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Matrisberäkningar med för STM32?

Inlägg av bearing »

Jag vet inte så mycket om detta, men några skrev något om fragmentering, och då har jag en gissning.

Låt säga att du har 400 byte heap. Du allokerar matris1, 100byte, följt av matris2, 200 byte. Då är 300 av 400 byte upptagna, 100 byte ledigt. matris1 har adressen heap_start, och matris2 heap_start + 100. Efter detta frigör du matris1. 200 av 400 byte är nu upptagna, d.v.s 200 byte ledigt. Då försöker du allokera matris3, 200 byte. Men det misslyckas! (eftersom att heapen inte har 200 byte sammanhängande minne ledigt)

Ingen aning om detta var en anledning till att inte använda heap, utan en gissning.

Med stacken så frigörs alltid minnet automatiskt i omvänd ordning från allokering, vilket inte ger detta problem. Med heap gäller det att "manuellt" se till så att heapen inte börjar fragmenteras, för då kommer det till slut inte gå att allokera stora matriser, bara små. Och det är nog inte helt enkelt att analysera programmet för att garantera att detta aldrig sker.
Användarvisningsbild
AndLi
Inlägg: 18096
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av AndLi »

Al_Bundy skrev:Jag har koll på minnet. Men var det inte detta som var ett problem enligt ni?

När jag deklarerar en array så lägga det på stacken. Samma sak när jag deklarerar med malloc? Vad är skillnaden?
Malloc lägger sig inte på stacken utan på heapen...
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av Al_Bundy »

Tack!

Då vet jag att det är säkert att använda arrayer i funktioner inom C :)
Gimbal
Inlägg: 8570
Blev medlem: 20 april 2005, 15:43:53

Re: Matrisberäkningar med för STM32?

Inlägg av Gimbal »

När jag höll på med inbyggda system så skulle all minnesallokering ske under uppstart, sedan fick det inte röras. Man tog till sig det man behövde en gång för alla. Dvs ingen risk för misslyckad allokering efter att uppstarten gått igenom.

Sen beror det förstås på applikationen om det är en gångbar metod.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av Al_Bundy »

Jag har gjort om mitt bibliotek att vid uppstart så allokerar man alla matriser och vektorer som man vill jobba med. Sedan får man återanvända dessa vid behov.
bearing
Inlägg: 11653
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Matrisberäkningar med för STM32?

Inlägg av bearing »

Al_Bundy skrev:Tack!

Då vet jag att det är säkert att använda arrayer i funktioner inom C :)
Hm...
Ja alltså det har ju inte främst med C att göra. Huruvida programmet har gigabytes att röra sig med (PC) eller kilobytes (MCU) har ju stor betydelse i sammanhanget, och vad som är att rekommendera eller inte.

På en MCU får man sätta upp en minneskarta (oavsett om programmeringsspråket är C, C++, eller Assembler), där man väljer placering och storlek på de olika minnesområdena (Statisk RAM, Stack, Heap, m.m.). Detta använder länkaren när den bygger binärfilen som ska flashas. Ifall du "säkert" kan allokera stora arrayer på stacken på din MCU har ju så klart att göra med hur mycket minne du valt att stacken ska få utnyttja. Och med tanke på att stacken på en MCU normalt inte är så stor, väljer man därför den säkrare vägen, att placera stora arrayer i statisk RAM, för att inte riskera att överfylla stacken.

Men minne och hastigheter på MCUer blir allt större, så i takt med detta kan det hända att utvecklingen går mot att oftare allokera minne. Men jag skulle aldrig göra det i mina program, så länge det inte finns väldigt bra skäl till det.
Användarvisningsbild
Icecap
Inlägg: 26610
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Matrisberäkningar med för STM32?

Inlägg av Icecap »

Al: i ett givet projekt, hur många samtidiga matriser behövs?

Jag förstår att du har en med indata.
Du har en med ut-data.
Och jag skulle omedelbart anse att det kan behövas ytterligare en med historiska data.
Alltså 3 st.

Sedan nog en att räkna med, typ mellanresultat.
Totalt 4 st.

Mellanresultatet kan ju återanvändas gång efter gång.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av Al_Bundy »

bearing skrev:
Al_Bundy skrev:Tack!

Då vet jag att det är säkert att använda arrayer i funktioner inom C :)
Hm...
Ja alltså det har ju inte främst med C att göra. Huruvida programmet har gigabytes att röra sig med (PC) eller kilobytes (MCU) har ju stor betydelse i sammanhanget, och vad som är att rekommendera eller inte.

På en MCU får man sätta upp en minneskarta (oavsett om programmeringsspråket är C, C++, eller Assembler), där man väljer placering och storlek på de olika minnesområdena (Statisk RAM, Stack, Heap, m.m.). Detta använder länkaren när den bygger binärfilen som ska flashas. Ifall du "säkert" kan allokera stora arrayer på stacken på din MCU har ju så klart att göra med hur mycket minne du valt att stacken ska få utnyttja. Och med tanke på att stacken på en MCU normalt inte är så stor, väljer man därför den säkrare vägen, att placera stora arrayer i statisk RAM, för att inte riskera att överfylla stacken.

Men minne och hastigheter på MCUer blir allt större, så i takt med detta kan det hända att utvecklingen går mot att oftare allokera minne. Men jag skulle aldrig göra det i mina program, så länge det inte finns väldigt bra skäl till det.

Jag allokerar endast bara för att få en dynamisk array bara. Jag tror att jag kommer klara av med mina 36x36 matriser.
Icecap skrev:Al: i ett givet projekt, hur många samtidiga matriser behövs?

Jag förstår att du har en med indata.
Du har en med ut-data.
Och jag skulle omedelbart anse att det kan behövas ytterligare en med historiska data.
Alltså 3 st.

Sedan nog en att räkna med, typ mellanresultat.
Totalt 4 st.

Mellanresultatet kan ju återanvändas gång efter gång.
Typ 15-20 stycken tror jag. Storleken är typ 36x36.

Nu fick jag svar från Armadillo.
Using the H matrix generated by the code you're sent, the reason you're getting different results is that for any singular value that is close to zero (eg. 1.0724e-15), the corresponding singular vectors are in effect garbage.

Armadillo and Octave pretty much agree on all the singular values, and they agree on the first two singular vectors (where the corresponding singular values are 1.4958e+00 and 1.0602e+00). For the remaining singular vectors, there is disagreement, but you're in effect comparing garbage to garbage.

In other words, the differences are not worth worrying about. If you're relying in specific garbage produced by either Octave or Matlab, I suggest refactoring your algorithm to be aware of the garbage results.

Alltså var det språket som var "felet" på. GNU Octave kunde hantera "skitdata", vilket inte C++ eller C kunde.
Shimonu
Inlägg: 311
Blev medlem: 21 oktober 2015, 22:44:33

Re: Matrisberäkningar med för STM32?

Inlägg av Shimonu »

Hur kommer du fram till det? Jag laser ingenstans i svaret att de säger att du använder fel språk eller att du måste byta. Däremot sags det att skillnaden inte spelar roll och om du är beroende av värdena får du ändra >>DIN ALGORITM<< för att hantera skräpdatat.
Skriv svar