[c++] Simd

[Moepi]1

Lt. Commander
Registriert
Jan. 2002
Beiträge
1.233
Ich versuche mich gerade in SIMD Programmierung mit C++. Dazu habe ich folgendes Codefragment:

Code:
#include <iostream>
#include <fvec.h>
#include <malloc.h>


float skalarproduktSSE(float *x, float *y)
{
	F32vec4 *vecX = (F32vec4 *)x;
	F32vec4 *vecY = (F32vec4 *)y;
	F32vec4 tmp;
 
	tmp = vecX[0] * vecY[0];
 
	return tmp[0] + tmp[1] + tmp[2] + tmp[3];
}


int main()
{
	float x[] = {1,2,3,4};
	float y[] = {1,2,3,4};
	
	std::cout << skalarproduktSSE(x,y) << std::endl;
}

Das obige funktioniert. Wenn ich jetzt aber dynamische Arrays wie folgt erstelle...
Code:
	int n = 4;
	
	float *x = (float*) malloc(n*sizeof(float));
	float *y = (float*) malloc(n*sizeof(float));
	
	for(int i=0; i<n; i++)
	{
		x[i] = i+1;
		y[i] = i+1;
	}
...dann schmiert mir das Programm zur Laufzeit ab. Daraus folgere ich, dass es zwischen den beiden Wegen, ein Array zu erstellen, einen gravierenden Unterschied zu geben. Daher meine Frage: Was genau ist der Unterschied zwischen:
Code:
float x[4];
float *x = (float*) malloc(4*sizeof(float));
?
 
Man du weisst gar nicht wie du mich mit der Frage abgelenkt hast ;) hab 30 min gegrübelt, aber ich glaub ich habs: Es gibt keinen Unterschied ;)


Aber laut Galileo musst du statt:
Code:
array[0]
einfach
Code:
*array
verwenden. Denn so wie ich das seh, will der SIMD befehl keinen Zeiger auf den Speicherbereich, sondern den 1. Wert des Arrays

Edit: Hmpf ... aber genau das hast du ja ... NARF! :) Wenn du die Lösung hast, lass es mich wissen ;)
 
Zuletzt bearbeitet:
1.
Code:
float x[4];
Du hast auf dem Stack eine Variable mit dem Namen x die in einem Feld der Größe 4*sizeof(float) Zahlen speichern kann.

2.
Code:
float* y = (float*) malloc(4*sizeof(float));
Du hast auf dem Stack eine Variable y die auf den Heap zeigt. An der "verzeigerten" Stelle gibt es eine Feld der Größe 4*sizeof(float).

Im ersten Fall ist x das Feld selbst.
Im zweiten Fall ist y nur ein Zeiger auf ein Feld und nicht das Feld selbst.
 
Ergänzend kann man noch sagen, dass ein Array bei der kleinsten Kleinigkeit auf einen Zeiger auf sein erstes Element konvertiert. Durch diesen Umstand sind viele Leute der Ansicht, Arrays und Pointer wären dasselbe.

Ich kann mir aber nicht vorstellen, dass das Programm bei dynamisch allokiertem Speicher abstürzen soll. Klingt eher nach einem anderen Problem.

Btw, warum malloc und nicht new?
 
Zuletzt bearbeitet:
Ich bin kurz vorm Ausrasten. Das Programm ist genau so wie oben gepostet und es läuft, wenn ich statische Arrays (also array[4] ) verwende. Bei dynamischen Arrays schmierts mir ab, interessanter weise aber erst bei Feldgrößen ab 4 oder mehr. Also mit nem malloc 3*sizeof gehts nocht !?!
Wenn ich den Speicher statt mit malloc mit new zuweise, wirds noch geiler: Dann berechnet er offenbar für n=4 den Wert noch, gibt ihn auch zurück (die Main kann ihn via std::cout sogar auf die Konsole schreiben), dafür stürzt der Sch*** danach ab! Ich bin kurz davor den Schmarn mit Inline-Assembler zu schreiben....


/Edit: Lösung
Also, für SIMD scheinen die Daten in 16 Byte große Blöcke strukturiert werden zu müssen. Und das erreicht man via:
Code:
float *x = (float*) _mm_malloc(n*sizeof(float),16);
float *y = (float*) _mm_malloc(n*sizeof(float),16);

Mehr dazu kann man auf http://www.x86.org/articles/sse_pt3/simd3.htm und http://parallel.ru/docs/Intel/c_ug/linux117.htm nachlesen.
 
Zuletzt bearbeitet:
Naja, nicht 16-Byte große Blöcke, aber die Daten müssen an 16-Byte-Grenzen ausgerichtet sein. Sprich die Speicheradresse muss durch 16 teilbar sein. Die Floats liegen danach schon sofort direkt im Speicher, wenn ich das richtig verstehe. Sonst würde die Array-Variante ja auch nicht funktionieren. (Wobei ich es für Zufall halte, dass das Array an einer 16-Byte ausgerichtet ist)
 
Hallo Moepi,

also ich habe nur mal ein bisschen gegoogelt. Aber daraus schliesse ich das diese f32vec4 Klasse nicht ganz so simpel gestrickt ist, als das man einfach ein float Array darauf casten kann. Der [] Operator ist anscheinend überladen und das funktioniert mit einem float Array dann eben nicht.

Zum einen ist also der erste Fehler das Du mit malloc arbeitest und ein cast von float* auf f32vec4* ist auch nicht die feine Art.

Von daher ist der Absturz doch erst mal nicht erstaunlich. Es sollte doch einen "offiziellen" Weg geben die Daten ein so ein Objekt reinzubekommen.
Notfalls in dem Du die Objekte explizit mit new anlegst und die Werte dem Konstruktor übergibst.

MfG

Arnd
 
Arnd schrieb:
Hallo Moepi,

also ich habe nur mal ein bisschen gegoogelt. Aber daraus schliesse ich das diese f32vec4 Klasse nicht ganz so simpel gestrickt ist, als das man einfach ein float Array darauf casten kann. Der [] Operator ist anscheinend überladen und das funktioniert mit einem float Array dann eben nicht.

Zum einen ist also der erste Fehler das Du mit malloc arbeitest und ein cast von float* auf f32vec4* ist auch nicht die feine Art.

Von daher ist der Absturz doch erst mal nicht erstaunlich. Es sollte doch einen "offiziellen" Weg geben die Daten ein so ein Objekt reinzubekommen.
Notfalls in dem Du die Objekte explizit mit new anlegst und die Werte dem Konstruktor übergibst.

MfG

Arnd


Naja ich hab jetzt versucht das ganze in Assembler zu machen. Ich seh einfach nicht ein, warum es nicht geht. Die Pointer stimmen, das Alignment stimmt, die Register sind ok - ich könnt weinen... :heul:
Will mit meinem TGI Prof nen Tag in ne Kammer gesperrt werden!! Der könnt mir das sicher erklären....
 
Hast Du mal geschaut, ob es nicht doch an was Anderem liegt ?
Bekommst Du eine Fehlermeldung ?
Hast Du mal Valgrind probiert ?

-- -- muckelzwerg
 
Ich kenne jetzt den Code zu der Klasse nicht. Wenn der [] operator überladen ist, ausserdem die Klasse intern anders strukturiert ist als einfach nur float Membervariablen zu besitzen, ist es wie gesagt kein Wunder.

Nimm einfach mal an im [] operator wird noch auf eine zusätzliche interne Variable zugegriffen, dann würdest Du durch den cast jedesmal in undefinerten Speicher greifen.

Vergleich doch mal ein sizeof(F32vec4) mit der Grösse von 4 floats. Wenn die unterschiedlich sind, dann hast Du denn Grund.

MfG

Arnd
 
Zurück
Oben