Ist XOR schneller/effizienter?

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Antworten
MoonGuy
Beiträge: 231
Registriert: Fr Okt 08, 2010 2:49 pm

Ist XOR schneller/effizienter?

Beitrag von MoonGuy » Mi Okt 27, 2010 10:11 pm

Hallo Leute,

also ich habe vor langer Weile mal einen Artikel gelesen(allerdings im Bereich der E-Technik), dass eine Variable zu "XOR"en schneller seie, als sie mit <variable> = 0 zurückzusetzen. Ist mir vor 5 Minuten wieder in den Kopf gekommen, deshalb hatte ich das ganze mal mit einem Testprogramm überprüft. Einmal Variable mit 0 zurücksetzen, einmal mit XOR. Es kam heraus:
Wert auf 0 setzen:
(4 Versuche)
execution time : 0.032 s
execution time : 0.021 s
execution time : 0.016 s
execution time : 0.021 s
XOR:
execution time : 0.016 s
execution time : 0.016 s
execution time : 0.016 s
execution time : 0.016 s
Nun meine Frage: Ist das ganze wirklich schneller(Okay, die Zeiten sind bei XOR konstant, aber einmal ist mit = 0 eine gleiche Zeit gerundet worden), und wenn ja, wieso? Zusätzlich als Frage: Wenn ihr Codes schreibt, benutzt ihr XOR oder = 0(außer beim initialisieren)? Würde euch die Zeitersparnis zum Umdenken verleiten?

P.S.: Ich denke, dass dieses Thema hierhin gut passt, da in der Threadbeschreibung steht: "(...)Sprachunabhängige Diskussionen(...)"

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Ist XOR schneller/effizienter?

Beitrag von cloidnerux » Mi Okt 27, 2010 10:16 pm

Es kann vlt damit zusammenhängen, dass der Compiler bei "=0" die 0 als Variable handhabt und mehr ASM-Code generiert, als wenn er hoch optimiert die Binäre Operation "XOR" Durchführt. Aber ich nutze meistens =0.
Was du vlt auch beachten solltest ist die Trägheit deines Timers, der vlt auch für ein Leeres Programm 16ms Ausspuckt, was mir für wenige Operationen auf einer Ghz schnellen Maschine sehr suspekt ist.
Redundanz macht wiederholen unnötig.
quod erat expectandum

MoonGuy
Beiträge: 231
Registriert: Fr Okt 08, 2010 2:49 pm

Re: Ist XOR schneller/effizienter?

Beitrag von MoonGuy » Mi Okt 27, 2010 10:19 pm

cloidnerux hat geschrieben:Was du vlt auch beachten solltest ist die Trägheit deines Timers, der vlt auch für ein Leeres Programm 16ms Ausspuckt, was mir für wenige Operationen auf einer Ghz schnellen Maschine sehr suspekt ist.
Deshalb schrieb ich ja auch gerundet in meinem ersten Beitrag.
Soweit ich weiß laufen viele Timer doch auch auf nur 10ms genau, war das nicht mal so(?). Sodass man z.B. auch nicht auf 33FPS kam sondern auf (int)(33 / 10 * 10) oder sowas.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ist XOR schneller/effizienter?

Beitrag von Xin » Mi Okt 27, 2010 10:37 pm

MoonGuy hat geschrieben:Hallo Leute,

also ich habe vor langer Weile mal einen Artikel gelesen(allerdings im Bereich der E-Technik), dass eine Variable zu "XOR"en schneller seie,

Nun meine Frage: Ist das ganze wirklich schneller
Beim MC68000 war XOR tatsächlich schneller. Man konnte mit move.l #0, a0 ein Register mit dem Langwort nach dem Befehl löschen: dafür musste das Langwort aber halt gelesen werden. Mit moveq.l #0, a0 ist die #0 im moveq Befehl bereits einkodiert (darum gehen auch nur Zahlen von -8 bis +7, wenn ich mich recht entsinne). Aber das bedeutet, erst das Register gelöscht werden muss und dann das Nibble in das Register kopiert werden.
xor a0, a0 ist damit am schnellsten, da es in einem Takt abgearbeitet wird.

Heute CPUs sollten alles in einem Takt schaffen.

Zur Zeitmessung solche Dinge musst Du die Aufgabe so oft wiederholen, dass Du überhaupt eine Aussage treffen kann.
Beschreibe die Variable jeweils eine Milliarde mal. Dann bekommst Du brauchbarere Zahlen.
Wenn Du das nur einmal oder tausendmal machst, hast Du nur Nebeneffekte durch den Programmstart.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

MoonGuy
Beiträge: 231
Registriert: Fr Okt 08, 2010 2:49 pm

Re: Ist XOR schneller/effizienter?

Beitrag von MoonGuy » Mi Okt 27, 2010 10:51 pm

Also hier jetzt mit 2 Variablen + Zähler, welcher bis ULONG_MAX zählt.(Hatte erst 3 Variablen, aber nach über 3 Minuten exec time habe ich abgebrochen).

XOR:
"execution time : 26.310 s"
= 0:
"execution time : 26.312 s"

Wobei ich sagen muss, ich hatte bei 1 Variable + Zähler zu ULONG_MAX mit = 0 bessere Ergebnisse, allerdings habe ich diese verworfen, da Hintergrundanwendungen u.ä. dabei liefen.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Ist XOR schneller/effizienter?

Beitrag von Dirty Oerti » Mi Okt 27, 2010 11:34 pm

Xin hat geschrieben:Zur Zeitmessung solche Dinge musst Du die Aufgabe so oft wiederholen, dass Du überhaupt eine Aussage treffen kann.
Beschreibe die Variable jeweils eine Milliarde mal. Dann bekommst Du brauchbarere Zahlen.
Wenn Du das nur einmal oder tausendmal machst, hast Du nur Nebeneffekte durch den Programmstart.
Ich hatte die Zeitmessung zusätzlich dazu immer direkt im Testprogramm implementiert.
Funktioniert folgendermaßen:

Bevor die zu testende Operation ausgeführt wird einfach mal mit time() (oder genauerem, da gibt es glaub ich ein paar Sachen .. egal, es funktioniert auch so) die aktuelle Zeit nehmen und in einer Variablen speichern.
Dann die zu testende Operation in z.B. 2 Schleifen schön oft ausführen.
Anschließend (direkt im Anschluss) wieder die Zeit nehmen, dann davon die Startzeit subtrahieren und man hat die Zeit, die es gedauert hat, die Operationen auszuführen.

Das ganze kann man auch abwandeln und die Operationen eine feste Zeit lang laufen lassen (das impliziert aber, dass nach jeder Operation auch getestet werden muss, ob die Zeit um ist) und zu zählen, wie oft die Operation ausgeführt wurde.
Nachteil ist nunmal, dass man mit normalen int Variablen als Zähler gerne mal Überläufe produziert und man außerdem deutlich mehr an Code ausführt, die Berechnung also ungenauer werden müsste.

Eventuell ist clock() auch noch besser geeignet als time()
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Ist XOR schneller/effizienter?

Beitrag von Xin » Do Okt 28, 2010 3:42 pm

MoonGuy hat geschrieben:Also hier jetzt mit 2 Variablen + Zähler, welcher bis ULONG_MAX zählt.(Hatte erst 3 Variablen, aber nach über 3 Minuten exec time habe ich abgebrochen).

XOR:
"execution time : 26.310 s"
= 0:
"execution time : 26.312 s"
Das entspricht dem, was ich erwartet habe. Hier gibt es zwei Möglichkeiten, weshalb:
1. Der Compiler optimiert in beiden Fällen, optimierungen sollten also abgeschaltet sein. Im Idealfall würde er die Schleifen zu einer Anweisung zusammenfassen, den egal wie oft Du 0 zuweist, einmal hät's auch getan.
2. Die Anweisungen sind gleichschnell. Von einer modernen CPU (jünger als 10 Jahre) würde ich das auch erwarten.
Dirty Oerti hat geschrieben:Eventuell ist clock() auch noch besser geeignet als time()
http://www.proggen.org/doku.php?id=theory:time:start

Für Linux muss ich das noch fertig machen...
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

MoonGuy
Beiträge: 231
Registriert: Fr Okt 08, 2010 2:49 pm

Re: Ist XOR schneller/effizienter?

Beitrag von MoonGuy » Fr Okt 29, 2010 3:09 pm

XOR:
"Der Vorgang dauerte 21968 Ticks."
= 0:
"Der Vorgang dauerte 19437 Ticks."

*schmunzel*
1. Der Compiler optimiert in beiden Fällen, optimierungen sollten also abgeschaltet sein. Im Idealfall würde er die Schleifen zu einer Anweisung zusammenfassen, den egal wie oft Du 0 zuweist, einmal hät's auch getan.
Ich setzte die Variable vorher immer auf den Wert des Counters:

Code: Alles auswählen

    while( counter < ULONG_MAX )
    {
        test_var = counter;
        test_var = 0;

        counter++;
    }
(Bzw. mit XOR)

Okay, könnte natürlich sein, dass der Compiler sagt, oh er weist in zwei Zeilen der selben Variable 2 mal verschiedene Werte zu und kickt die erste Anweisung... Aber dann müsste der Compiler auch erkannt haben, dass in der ersten Anweisung keine Funktion aufgerufen wird...

============

Meinungen?

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Ist XOR schneller/effizienter?

Beitrag von cloidnerux » Fr Okt 29, 2010 4:30 pm

Meinungen?
Ja, ich hab mal auf meinem System(AMD 5600+X2, 3GB Ram, Win 7 32-Bit) einige Test gemacht.
Jeweils 2 Durchläufe Binäres XOR und "=0" immer abwechselnd. Genaueres dem log entnehmen:
Ohne Optimierung 80%, Binäres Xor und 0 zuweisung, Last auf 1 Kern:
Elpased time: 13.947864 <-- XOR
Elapsed time: 12.446341 <-- =0
Elapsed time: 14.202977 <-- XOR
Elpased time: 11.516644 <-- =0

Mit Optimierung 02, Binäres Xor und 0 zuwesiung, last auf 80%
Elpased time: 3.157472
Elapsed time: 3.111312
Elapsed time: 3.120224
Elpased time: 3.108974

Ohne Optimierungen Test 2,XOR und =0, last auf 80%
Elpased time: 14.894090
Elapsed time: 11.732605
Elapsed time: 14.202121
Elpased time: 11.794209

Ohne Optimierungen, XOR und var = zero, last 70%
Elapsed time: 13.309708
Elapsed time: 12.558499
Elapsed time: 13.150562
Elpased time: 12.535947

Ohne Optimierungen, Binäres & anstatt XOR , last 70%
Elapsed time: 12.003709
Elapsed time: 12.666582
Elapsed time: 12.091115
Elapsed time: 12.515890
Sizeof unsigned long: 4, size of int: 4

Ohne Optimierungen, Binäres Xor als Refernz, last 50%
Elapsed time: 13.207295
Elapsed time: 12.530253
Elapsed time: 13.100630
Elapsed time: 12.520988
Sizeof unsigned long: 4, size of int: 4
Hier der Source Code des Programms:

Code: Alles auswählen

// PerformanceTest.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//Visual Studio 2008, Win32 Konsolenanwendung ohne statische Header

#include "stdafx.h" //<--#include <stdio.h> #include <tchar.h>
#include <conio.h>
#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
	unsigned long var = 1337;
	unsigned long zero = 0;
	unsigned long long counter = 0;
	LARGE_INTEGER start, end, frequency;
 
	if(!QueryPerformanceFrequency(&frequency))
	{
		printf("Error intialising time\n");
		return  0;
	}
	QueryPerformanceCounter(&start);
 
	for(; counter < 0xffffffff; counter++)
	{
		var = 1337;
		var >>= 2^32;
	}
 
	QueryPerformanceCounter(&end);
	double elapsed = (double)(end.QuadPart  - start.QuadPart) / (double)(frequency.QuadPart);
	printf("Elapsed time: %f \n", elapsed);

	QueryPerformanceCounter(&start);
 
	for(counter = 0; counter < 0xffffffff; counter++)
	{
		var = 1337;
		var = zero;
	}
 
	QueryPerformanceCounter(&end);
	elapsed = (double)(end.QuadPart  - start.QuadPart) / (double)(frequency.QuadPart);
	printf("Elapsed time: %f \n", elapsed);

	QueryPerformanceCounter(&start);
 
	for(counter = 0; counter < 0xffffffff; counter++)
	{
		var = 1337;
		var ^= var;
	}
 
	QueryPerformanceCounter(&end);
	elapsed = (double)(end.QuadPart  - start.QuadPart) / (double)(frequency.QuadPart);
	printf("Elapsed time: %f \n", elapsed);

	QueryPerformanceCounter(&start);
 
	for(counter = 0; counter < 0xffffffff; counter++)
	{
		var = 1337;
		var = zero;
	}
 
	QueryPerformanceCounter(&end);
	elapsed = (double)(end.QuadPart  - start.QuadPart) / (double)(frequency.QuadPart);
	printf("Elapsed time: %f \n", elapsed);
	printf("Sizeof unsigned long: %d, size of int: %d\n", sizeof(unsigned long), sizeof(int));
	_getch();
	return 0;
}

Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten