Hur snabbare är uint vs float?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Hur snabbare är uint vs float?

Inlägg av sodjan »

Alltså... Vilka parametrar som som man tittar på bör väl vara desamma som de som är viktiga för applikationen? Om FP prestanda är viktigt så är det väl (bl.a.) FPU som man speciellt tittar på.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Jo. Det kollar jag verkligen noga på.

Just nu försöker jag lösa ett optimeringsproblem som liknar.

\(\dot x = 5x^2 - yx + 6y^3 + 6u_1^3 - 2u_2^5 + xu_1^2 + 7u_1u_2\)
\(\dot y = 7 - x + 6y^5 + 2y^2 + 6u_1^3 - 3u_2^5 + u_1u_1^2 + 9u_1\)

Där \(\dot x = \dot y = 0\) och målet är att jag ska hitta \(u_1, u_2\) där \(u_1 \geq 0, u_2 \geq 0\) samt att \(u_1, u_2\) måste vara så liten som möjligt. Variablerna \(x, y\) är kända som konstanter.

Detta ska bli kul. Jag har en idé :)
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Vad får ni för snabbhet när ni kör denna?
Jag får 0.001 om jag inte anropar print_vector.

Ni får gärna komma med pekpinnen och bekräfta vad man kan göra för att det ska gå snabbare.
Det denna gör är att den hittar alla kombinationer hos vektorn \(u\) mellan \(0\) till \(30\) med steget \(1\).

Kod: Markera allt

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <math.h>

void increment(uint8_t* index, float* u, uint8_t* elements, float* step, float* max_value, float* min_value){
	if(*index >= *elements - 1)
		return;
	*index = *index + 1;
	u[*index] += *step;
	if(u[*index] > *max_value){
		u[*index] = *min_value;
		increment(index, u, elements, step, max_value, min_value);
	}
	*index = *index - 1;
}

void print_vector(float* A, int row, int column) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < column; j++) {
			printf("%f\t", *(A++));
		}
		printf("\n");
	}
	printf("\n");
}

int main() {

	// Initial parameters
	float u[3] = {0,0,0};
	uint8_t elements = 3;
	float min_value = 0;
	float max_value = 30;
	float step = 1;

	// Start clock
	clock_t start, end;
	float cpu_time_used;
	start = clock();

	// Do the process
	uint8_t index = 0;
	for(uint32_t i = 0; i < powf(max_value - min_value + 1, elements); i++){
		for(float j = min_value; j <= max_value; j += step){
			u[index] = j;
			print_vector(u, 1, elements);
		}
		increment(&index, u, &elements, &step, &max_value, &min_value);
	}

	// Compute the speed
	end = clock();
	cpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;
	printf("\nTotal speed  was %f\n", cpu_time_used);

	return EXIT_SUCCESS;
}
Användarvisningsbild
AndLi
Inlägg: 17045
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Hur snabbare är uint vs float?

Inlägg av AndLi »

jag får 0.008770
I vilken enhet anser du att det är?
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Det vet jag inte riktigt. Jag tror det är bara ett förhållande.

Tanken är att jag ska lösa denna ekvation ovan med denna algoritm :) Jag har testat använda simuleringar som använder gradienter, men problemet är att dom tenderar alltid att fastna i lokala minimum. Inte bra. Därför tänkte jag testa och pröva alla olika värden och se vilket värde som ger bäst resultat. Skit samma om det tar 20 sekunder längre än professionella metoder tycker jag.
Användarvisningsbild
AndLi
Inlägg: 17045
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Hur snabbare är uint vs float?

Inlägg av AndLi »

Ett förhållande mellan vad? tiden och CLOCKS_PER_SEC? Kan du ens jämföra det tal du får ut mellan olika datorer, och vad är vinsten att jämföra mellan olika datorer? Är det inte mellan dina egna olika implementationer du vill jämföra så du vet om det blir bättre?
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Jag tror talet är ett mått på ett värde som ska vara förhållandet tiden och klockcyklerna, ja.
Tittar man på ekvationen så är det tydligt (end - start)) / CLOCKS_PER_SEC.

Formeln är T2-T1, där T2 och T2 är CPU tid.
Detta delas med CLOCKS_PER_SEC som är ett mått på hur många klockcykler per sekund.

Hur som helst så är jag klar med min algoritm.

Denna hittar alltså lösningen till Ax=b systemet.

Kod: Markera allt

>> A = [5 10; -4 5]
A =

    5   10
   -4    5

>> b = [53 + 8; 3 + 7]
b =

   61
   10

>> x = linsolve(A, b)
x =

   3.1538
   4.5231

>>

Min lösning med denna C-kod blev.

Kod: Markera allt

3.159	4.520
När jag körde detta ekvationssystem. Vektorn b kan betraktas som konstant.

Kod: Markera allt

void func(float* dx, float* b, float* x){
	dx[0] = 53*b[0] + 8*b[1] - (5*x[0] + 10*x[1]);
	dx[1] = 3*b[0] + 7*b[1] - (-4*x[0] + 5*x[1]);
}
I nedre fallet så använder jag mig utav ett mycket olinjärt ekvationssystem.

Kod: Markera allt

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <math.h>

void increment(uint8_t* index, float* x, uint8_t* elements, float* step, float* max_value, float* min_value){
	if(*index >= *elements - 1)
		return;
	*index = *index + 1;
	x[*index] += *step;
	if(x[*index] > *max_value){
		x[*index] = *min_value;
		increment(index, x, elements, step, max_value, min_value);
	}
	*index = *index - 1;
}

void check_solution(float* dx, float* x, float* past_sum_dx, float* best_x, uint8_t* elements){
	// Do L2-norm on dx
	float sum = 0;
	for(uint8_t i = 0; i < *elements; i++){
		sum += dx[i]*dx[i];
	}
	sum = sqrtf(sum);

	// Check the condition
	if(*past_sum_dx > sum){
		*past_sum_dx = sum;
		memcpy(best_x, x, sizeof(float)* *elements);
	}
}

void nonlinsolve(void (*nonlinear_equation_system)(float*, float*, float*), float* b, float* x, uint8_t elements, float step, float max_value, float min_value){
	// Initial parameters and arrays
	uint8_t index = 0;
	float dx[elements];
	float past_sum_dx = FLT_MAX;
	float best_x[elements];

	// Do the process
	for(uint32_t i = 0; i < powf(max_value - min_value + 1, elements); i++){
		for(float j = min_value; j <= max_value; j += step){
			x[index] = j;
			(*nonlinear_equation_system)(dx, b, x);
			check_solution(dx, x, &past_sum_dx, best_x, &elements);
		}
		increment(&index, x, &elements, &step, &max_value, &min_value);
	}

	// Copy over our final solution x
	memcpy(x, best_x, sizeof(float)*elements);
}

void print(float* A, int row, int column) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < column; j++) {
			printf("%0.18f\t", *(A++));
		}
		printf("\n");
	}
	printf("\n");
}

void func(float* dx, float* b, float* x){
	dx[0] = 53*b[0] + 8*b[1] - (5*x[0]*x[0] + 10*x[1]*x[1]*x[1]);
	dx[1] = 3*b[0] + 7*b[1] - (-4*x[0] + 5*x[1]*x[0]);
}

int main() {

	// Initial parameters
	float x[2] = {0,0};
	float b[2] = {1, 1};
	uint8_t elements = 2;
	float min_value = -50;
	float max_value = 70;
	float step = 0.001;

	// Start clock
	clock_t start, end;
	float cpu_time_used;
	start = clock();

	// Do the process
	nonlinsolve(func, b, x, elements, step, max_value, min_value);

	printf("Solution:\n");
	print(x, 1, elements);
	printf("Accuracy:\n");
	float dx[elements];
	func(dx, b, x);
	print(dx, 1, elements);

	// Compute the speed
	end = clock();
	cpu_time_used = ((float) (end - start)) / CLOCKS_PER_SEC;
	printf("\nTotal speed  was %f\n", cpu_time_used);

	return EXIT_SUCCESS;
}
hummel
Inlägg: 2259
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: Hur snabbare är uint vs float?

Inlägg av hummel »

Solution:
-3.489779949188232422 0.227000281214714050

Accuracy:
-0.009792327880859375 0.001785278320312500


Total speed was 21.735413
Program ended with exit code: 0
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Samma här!

Nu tar detta lite lång tid, men det har med att jag har fixerat steg som den stegar sig framåt. Bästa vore om det kunde vara adaptivt.

För att få det adaptivt så mäter man skillnaden mellan dx. Om skillnaden mellan dx krymper, så kan man krympa antalet steg också. Men om skillnaden mellan dx ökar, så kan man öka antalet steg.

Då går det snabbare.
Jag ska lägga in så att man kan få minimering och maximering också.

Om ni undrar vad sjutton jag håller på med så håller jag på att lösa olinjära ordinära differentialsekvationer på första ordningen.
Varför?
Jo, för att beräkna mig vilka insignaler jag ska ha när systemet är statiskt. Statiskt är ett system när systemet har hittat sin rätta position.
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Hur snabbare är uint vs float?

Inlägg av Rick81 »

Kod: Markera allt

for(uint32_t i = 0; i < powf(max_value - min_value + 1, elements); i++){
Testa om detta går snabbare (kan hända optimering hittar det själv dock):

Kod: Markera allt

uint32_t count = powf(max_value - min_value + 1, elements);
for(uint32_t i = 0; i < count i++){
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Tackar så mycket Rick! Detta ska jag implementera. :tumupp:
hummel skrev: 3 juni 2021, 21:08:52 Solution:
-3.489779949188232422 0.227000281214714050

Accuracy:
-0.009792327880859375 0.001785278320312500


Total speed was 21.735413
Program ended with exit code: 0
Nu har jag fått detta resultat, med adaptivt steg.

Kod: Markera allt

Solution:
-3.489506006240844700	0.227000281214714050	

Accuracy:
-0.000232102669542655	0.002570198616012931	


Total speed  was 0.034000
Utan adaptivt steg.

Kod: Markera allt

Solution:
-3.489787578582763700	0.227000281214714050	

Accuracy:
-0.010057982988655567	0.001763494219630957	


Total speed  was 29.043000
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Hur snabbare är uint vs float?

Inlägg av DanielM »

Fråga!

Hur smart är detta om både past_sqrt_sum_dx och sqrt_sum_dx är floats? Tanken är att när lösningen x inte ändras, eller är så otroligt låg så att float blir snarare en konstant, då körs if-satsen.
På PC fungerar detta utmärkt. Där kan man se att sqrt_sum_dx får värden typ som 0.00000434343543545 osv och dom håller sig konstanta efter ca 200 iterationer. Men hur blir det då på uC?

Lösningen x uppdateras konstant hela tiden, men i väldigt små steg. Så små så att inte ens float ändras.

Kod: Markera allt

                // Check the solution if it's good or not
		sqrt_sum_dx = check_solution(dx, x, &best_sqrt_sum_dx, best_x, &elements);

		// If sqrt_sum_dx stands still - break
		if(past_sqrt_sum_dx == sqrt_sum_dx){
			break_count++;
			if(break_count >= times_until_break)
				break;
		}
		past_sqrt_sum_dx = sqrt_sum_dx;
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Hur snabbare är uint vs float?

Inlägg av Rick81 »

Det är inte bra köra exakt jämförelse på float då de pga avrundinngar kan bli fel så att ditt villkor aldrig kommer bli uppfyllt.

I vanliga fall när man jämförelse med ett rimligt gränsvärde. Ex

Kod: Markera allt

if(abs(past_sqrt_sum_dx - sqrt_sum_dx) < LIMIT)
{
....
}
Skriv svar