Sida 18 av 70
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 16:29:50
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.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 16:31:38
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.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 16:36:57
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.
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.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 17:06:57
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.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 17:31:10
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å.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 17:49:13
av AndLi
Vad har du för nytta av att multiplicera tre oinitierade matriser?
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 18:02:38
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å.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 18:44:50
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.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 19:05:53
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;
}
}
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 19:09:19
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
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);
}
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 22:51:55
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?
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 23:00:30
av Shimonu
Al_Bundy skrev:
Jag har gjort liknande, men vad mycket C-kod du skrev för just detta
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å.
Re: Matrisberäkningar med för STM32?
Postat: 15 januari 2019, 23:46:21
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.
Re: Matrisberäkningar med för STM32?
Postat: 16 januari 2019, 18:15:16
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?
Re: Matrisberäkningar med för STM32?
Postat: 16 januari 2019, 18:51:08
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.