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 »

Tanken är att man ska först göra sina beräkningar i MATLAB. Där efter ska man kunna använda likadana kommandon i C för att utföra sin MATLAB kod, fast i C.

Jag har tänkt på detta. Jag har dock inte lagt till det än.
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Matrisberäkningar med för STM32?

Inlägg av Mr Andersson »

Al_Bundy skrev:En fråga! Om jag ska kopiera värden från en matris till en annan, då skriver jag denna kod.
...
Där eye(n) retunerar en identitetsmatris. Måste jag radera denna eye(n) efter jag har "kört klart" copyval(matrix* a, matrix* b) ? Eller beror det på vilken kompilator jag använder? Just nu är det C11.
1) Använd memcpy, mycket snabbare än att kopiera individuella element.
2) Radering; Det beror på hur du skapar matrisen, inte vilken kompilator du har. Allt som är malloc'erat ska frigöras när du inte ska använda det mer. Men med det sagt så är ju identitetsmatriser både konstanta (ändras aldrig) och väldigt vanliga, så skapa dem en gång vid uppstart och hänvisa till samma matris varje 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 »

Okej. Jag ska använda memcpy. Så här blev det

Kod: Markera allt

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

	b->data = a->data; // Matris a och matrix b har samma dimension och samma datatyp.
	/*
	int n = b->row;
	int m = b->column;
	float* ptr_a = a->data;
	float* ptr_b = b->data;

	// copy all values from matrix a to matrix b
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			*(ptr_b++) = *(ptr_a++);
		}
	}
	*/
}
Ja. Så fort jag kopierar, så gör jag alltså en ny malloc på en matris som jag fyller på med värden. Sedan retunerar jag tillbaka denna matris. Jag har svårt för att radera , i samma funktion, det jag ska retunera tillbaka. :humm:

Istället för att skapa en matris som jag har som argument i en funktion. Så skapar jag matrisen direkt som argument. Matrisen är allokerad med minne. Så jag får inte tillbaka den.
Användarvisningsbild
mankan
EF Sponsor
Inlägg: 908
Blev medlem: 18 juli 2015, 11:23:22
Ort: Linköping

Re: Matrisberäkningar med för STM32?

Inlägg av mankan »

Al, mitt förslag är att alla funktioner tar in matrix* som argument oavsett om de är in eller ut-argument till funktionen. Då lägger du ansvaret på den som anropar funktionen att allokera minnet bäst hur den vill. Nackdelen är att att den som anropar måste ha koll på dimensionen av eventuella utargument. Behöver en funktion mellanlagra resultat kan du som sagt förallokera matriser till detta eller så börjar du med att allokera dem dynamiskt och optimerar senare.

Kod: Markera allt

// create gör malloc, sedan behöver du en destroy också.
matrix* x = create(3, 3);
matrix* y = create(1, 3);
matrix* z = create(3,3);

// Set values in x
set_scalar(3, y);
z = multiply(x, y, z); // här måste du även bestämma dig för om utargumentet får vara ett av inargumenten.
Börja skissa på header-filen för dina funktioner och torrhacka ett program som använder dina funktioner så ser du om API blir smidigt eller vilka kompromisser du behöver göra.
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 »

Just nu försöker jag bara få det att fungera. Men samtidigt vill jag inte göra dubbeljobb. Så optimering lämnar jag till sist.

Vi säger att din kod hade sett ut så här

Kod: Markera allt

// Set values in x
set_scalar(3, y);
matrix* z = multiply(create(3,3), create(1,3), create(3,3)); // här måste du även bestämma dig för om utargumentet får vara ett av inargumenten.
Hur hade du gjort nu? Du får matris z tillbaka. Men i argumenten så har du skapat tre matriser också.
Användarvisningsbild
AndLi
Inlägg: 17127
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Matrisberäkningar med för STM32?

Inlägg av AndLi »

Vad har du för nytta av att multiplicera tre oinitierade matriser?
Användarvisningsbild
mankan
EF Sponsor
Inlägg: 908
Blev medlem: 18 juli 2015, 11:23:22
Ort: Linköping

Re: Matrisberäkningar med för STM32?

Inlägg av mankan »

I C kan man göra:

Kod: Markera allt

matrix* x;
matrix* y;
matrix* z = multiply(y = set_scalar(3, create(1,3)), x = create(1,3), create(3,3));
Och då har du inte slavat bort något minne förutsatt du kör destroy() på dem senare.
Personligen tycker jag det är otydlig kod att ha tilldelningar inuti uttryck.

Sedan är ju detta kanske inte det bästa exemplet som AndLi påpekar såvida man inte kan initialisera matris x men koden blir ju ännu grötigare då.
Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: Matrisberäkningar med för STM32?

Inlägg av Shimonu »

I C går det rätt bra att dölja att man jobbar med pekare och kan ha upplevelsen av att man jobbar med objekt.

Matrix_Example.c

Kod: Markera allt

#include "Matrix_Example.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

Matrix_Element GetMatrixElement(Matrix SourceMatrix, uint32_t Row, uint32_t Column)
{
    return SourceMatrix->MatrixPosition[Row][Column];
}

Matrix EmptyMatrix(uint32_t Rows, uint32_t Columns)
{
    uint32_t Row;
    Matrix_Element **NewMatrixArray = 
        (Matrix_Element **) malloc(sizeof(Matrix_Element *) * Rows);
    
    for(Row = 0; Row < Columns; Row++)
    {
        NewMatrixArray[Row] = (Matrix_Element *) malloc(sizeof(Matrix_Element) * Columns);
    }
    
    Matrix NewMatrix = (Matrix) malloc(sizeof(Matrix_Type));
    
    NewMatrix->MatrixPosition = NewMatrixArray;
    NewMatrix->Rows = Rows;
    NewMatrix->Columns = Columns;
    
    return NewMatrix;
}

Matrix IdentityMatrix(uint32_t Rows, uint32_t Columns)
{
    Matrix NewMatrix = EmptyMatrix(Rows, Columns);

    uint32_t Row_Index;
    uint32_t Column_Index;

    for(Row_Index = 0; Row_Index < Rows; Row_Index++)
    {
        for(Column_Index = 0; Column_Index < Columns; Column_Index++)
        {
            if(Row_Index == Column_Index)
            {
                NewMatrix->MatrixPosition[Row_Index][Column_Index] = 1.0f;
            }
        }
    }

    return NewMatrix;
}

void PrintMatrix(Matrix MatrixToPrint)
{
    uint32_t Row_Index;
    uint32_t Column_Index;
    
    for(Row_Index = 0; Row_Index < MatrixToPrint->Rows; Row_Index++)
    {
        for(Column_Index = 0; Column_Index < MatrixToPrint->Columns; Column_Index++)
        {
            printf("%0.3f ", GetMatrixElement(MatrixToPrint, Row_Index, Column_Index));
        }
        printf("\n");
    }
    printf("\n");
}

int main()
{
    Matrix My_Matrix = IdentityMatrix(36, 36);
    
    PrintMatrix(My_Matrix);
    
    return 0;
}
Matrix_Example.h

Kod: Markera allt

#include "stdint.h"

typedef float Matrix_Element;

typedef struct
{
    Matrix_Element** MatrixPosition;
    uint32_t        Rows;
    uint32_t        Columns;
} Matrix_Type;

typedef Matrix_Type *Matrix;

Jag kommer inte ihåg hur det är nu med C++ och överlagring. Skulle man kunna få till en överlagrad operator som gör att man kan ha matrismultiplikation av stilen A * B * C? Jag ser inte vad hindret skulle vara.
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 »

AndLi skrev:Vad har du för nytta av att multiplicera tre oinitierade matriser?
Vektorisering.
mankan skrev:I C kan man göra:

Kod: Markera allt

matrix* x;
matrix* y;
matrix* z = multiply(y = set_scalar(3, create(1,3)), x = create(1,3), create(3,3));
Och då har du inte slavat bort något minne förutsatt du kör destroy() på dem senare.
Personligen tycker jag det är otydlig kod att ha tilldelningar inuti uttryck.

Sedan är ju detta kanske inte det bästa exemplet som AndLi påpekar såvida man inte kan initialisera matris x men koden blir ju ännu grötigare då.

Jo. Men kan jag göra som jag gjorde ovan, utan att det blir problem? Eller måste jag "dela" upp det och sedan köra destroy på de övriga? I mitt fall heter det "freeMatrix(matrix* a)" och koden ser ut så här.

Kod: Markera allt

void freeMatrix(matrix* m) {
	if (m != NULL) {
		if (m->data != NULL) {
			free(m->data);
			m->data = NULL;
		}

		free(m);
		m = NULL;
	}
}
Senast redigerad av Al_Bundy 15 januari 2019, 19:25:19, redigerad totalt 1 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 »

Shimonu skrev:I C går det rätt bra att dölja att man jobbar med pekare och kan ha upplevelsen av att man jobbar med objekt.

Matrix_Example.c

Kod: Markera allt

#include "Matrix_Example.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

Matrix_Element GetMatrixElement(Matrix SourceMatrix, uint32_t Row, uint32_t Column)
{
    return SourceMatrix->MatrixPosition[Row][Column];
}

Matrix EmptyMatrix(uint32_t Rows, uint32_t Columns)
{
    uint32_t Row;
    Matrix_Element **NewMatrixArray = 
        (Matrix_Element **) malloc(sizeof(Matrix_Element *) * Rows);
    
    for(Row = 0; Row < Columns; Row++)
    {
        NewMatrixArray[Row] = (Matrix_Element *) malloc(sizeof(Matrix_Element) * Columns);
    }
    
    Matrix NewMatrix = (Matrix) malloc(sizeof(Matrix_Type));
    
    NewMatrix->MatrixPosition = NewMatrixArray;
    NewMatrix->Rows = Rows;
    NewMatrix->Columns = Columns;
    
    return NewMatrix;
}

Matrix IdentityMatrix(uint32_t Rows, uint32_t Columns)
{
    Matrix NewMatrix = EmptyMatrix(Rows, Columns);

    uint32_t Row_Index;
    uint32_t Column_Index;

    for(Row_Index = 0; Row_Index < Rows; Row_Index++)
    {
        for(Column_Index = 0; Column_Index < Columns; Column_Index++)
        {
            if(Row_Index == Column_Index)
            {
                NewMatrix->MatrixPosition[Row_Index][Column_Index] = 1.0f;
            }
        }
    }

    return NewMatrix;
}

void PrintMatrix(Matrix MatrixToPrint)
{
    uint32_t Row_Index;
    uint32_t Column_Index;
    
    for(Row_Index = 0; Row_Index < MatrixToPrint->Rows; Row_Index++)
    {
        for(Column_Index = 0; Column_Index < MatrixToPrint->Columns; Column_Index++)
        {
            printf("%0.3f ", GetMatrixElement(MatrixToPrint, Row_Index, Column_Index));
        }
        printf("\n");
    }
    printf("\n");
}

int main()
{
    Matrix My_Matrix = IdentityMatrix(36, 36);
    
    PrintMatrix(My_Matrix);
    
    return 0;
}
Matrix_Example.h

Kod: Markera allt

#include "stdint.h"

typedef float Matrix_Element;

typedef struct
{
    Matrix_Element** MatrixPosition;
    uint32_t        Rows;
    uint32_t        Columns;
} Matrix_Type;

typedef Matrix_Type *Matrix;

Jag kommer inte ihåg hur det är nu med C++ och överlagring. Skulle man kunna få till en överlagrad operator som gör att man kan ha matrismultiplikation av stilen A * B * C? Jag ser inte vad hindret skulle vara.
Jag har gjort liknande, men vad mycket C-kod du skrev för just detta :o

Min print ser ut så här.

Kod: Markera allt

void printMatrix(matrix* m) {
	float* ptr = m->data;
	for (int i = 0; i < m->row; i++) {
		for (int j = 0; j < m->column; j++) {
			printf(" %9.6f", *(ptr++));
		}
		printf("\n");
	}
}

Varför deklarerade du uint32_t utanför forloopen?

Kod: Markera allt

    uint32_t Row;
    for(Row = 0; Row < Columns; Row++)
    {
        NewMatrixArray[Row] = (Matrix_Element *) malloc(sizeof(Matrix_Element) * Columns);
    }
Användarvisningsbild
AndLi
Inlägg: 17127
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:
AndLi skrev:Vad har du för nytta av att multiplicera tre oinitierade matriser?
Vektorisering.
Får man inte ut brus av att multiplicera brus med varandra?
Shimonu
Inlägg: 295
Blev medlem: 21 oktober 2015, 22:44:33

Re: Matrisberäkningar med för STM32?

Inlägg av Shimonu »

Al_Bundy skrev:
Jag har gjort liknande, men vad mycket C-kod du skrev för just detta :o

Min print ser ut så här.

Kod: Markera allt

void printMatrix(matrix* m) {
	float* ptr = m->data;
	for (int i = 0; i < m->row; i++) {
		for (int j = 0; j < m->column; j++) {
			printf(" %9.6f", *(ptr++));
		}
		printf("\n");
	}
}
Vad grötig och oläsbar din kod är. Våra funktioner för att skriva ut en matris ser ju näst intill identiska ut. Var har jag skrivit mycket kod?
Al_Bundy skrev: Varför deklarerade du uint32_t utanför forloopen?

Kod: Markera allt

    uint32_t Row;
    for(Row = 0; Row < Columns; Row++)
    {
        NewMatrixArray[Row] = (Matrix_Element *) malloc(sizeof(Matrix_Element) * Columns);
    }
Det är av vana efter att ha jobbat med gamla versioner av C där det är tvunget. Du ser, C utvecklas också.
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Matrisberäkningar med för STM32?

Inlägg av Mr Andersson »

Verkar som att Al på något sätt tror att antal kodlinjer är lika med prestanda.
Vektorisering har ingenting att göra med om saker är på samma rad eller inte. Dessutom har cm4f varken SIMD eller superskalär arkitektur så det är helt meningslöst att försöka vektorisera.
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 »

Okej! Det kanske är annat när det är lågnivåspråk.

Men hur var det med att ha ett allokerad argument i en funktion? Gör det något? Raderas den automatiskt efter funktionen har retunerats?
Användarvisningsbild
mankan
EF Sponsor
Inlägg: 908
Blev medlem: 18 juli 2015, 11:23:22
Ort: Linköping

Re: Matrisberäkningar med för STM32?

Inlägg av mankan »

Ursäkta tjatet:
mankan skrev:Det är hög tid att du lär dig hur stack och heap fungerar oavsett programspråk.
Vadå allokerat argument i en funktion?
En funktions argument läggs på stacken.
Skriv svar