[C/Bitwise] Kosten/Nutzen einer Einheit < 8 bit

Hi.

Es kann sich lohnen.

Als Beispiel könnte man die UseCompressedOops Option der Oracle JVM heranziehen, dabei werden interne "Zeiger" der JVM auf 64bit Maschinen in 32bit Zeiger "gepresst". Das spart Speicher, auf Kosten der Geschwindigkeit durch die notwendige Kodierung / Dekodierung. Allerdings kann ein solcher negativer Effekt evtl. wieder dadurch ausgeglichen werden, das in den Prozessor-Caches mehr Platz ist...

https://wikis.oracle.com/display/HotSpotInternals/CompressedOops
 
Caligulamins & Konkrete Bezugsgrößen:
Die konkrete Bezugsgröße ist 4M bzw. 5M.
Dein "ominöser" Ram ist hier fehl am Platz, der hat damit nichts zu tun.
Wenn 10 Leute von 1000 eine Krankheit haben, von denen nur 4 geheilt werden können,
und ich kann 6 kurieren ist das auch eine Steigerung von 50%, nicht von 0.2% (2/1000)
Wenn das neue Heilverfahren das Zehntausendfache kostet
(Im Rechner Speicher vs Geschwindigkeit) ist das natürlich auch zu berücksichtigen,
aber trotzdem werden 50% mehr geheilt (bzw. können geheilt werden)
 
@sheel: Ich bekomme den Eindruck, daß Du es ernshaft für nötig erachtest, mir Prozentrechnung beizubringen - echt jetzt?

Ich habe mich auf die Eingangsfrage bezogen, und die lautete nicht "Wieviel Prozent sind eins von fünf?".
 
Die Frage ist nur: Was mache ich, wenn es keinen kleineren Datentypen mehr gibt? Lohnt sich die Teilung oder bremst man das System damit zu stark?

Das ist pauschal leider nicht zu beantworten. Man kann den Compiler nebenbei so einstellen, dass er auf verschiedene Sachen optimiert, Laufzeit, Codegröße, Speicherbedarf etc. Wenn dein Compiler nun deinen Code so umbaut, dass er für das Shiften genauso lange braucht, wie für zwei einzelne Byte hast du in Sachen CPU nichst gewonnen. Daher ist es stark abhängig, was der Compiler genau macht, also letztendlich die benötigten Operationen pro Befehl.

Das kann man mit diversen Tests des Programms aber ermittelt werden (meistens aber erst bei sehr großen Datenmengen, wo die Zeiterfassung einigermaßen realistisch einzuschätzen ist.
 
@caligulaminus:
Ich hatte mich auch auf nichts Anderem bezogen.
Es ist gut möglich, dass ich einfach völlig falsch denke;
dann wäre ich sehr dankbar, wenn du mir in ein-zwei Sätzen sagst
was an meiner Rechnung nicht passt.

Und Posts, in denen es um Anteile geht
bekommen eben auch Reaktionen mit Prozenten.
Ganz egal, was man einem User zutrauen kann.
War jedenfalls nicht als Beleidigung aufzufassen.

PS: Sorry für OT
 
Hallo

@ComFreek
ich möchte hier nur folgenden Satz einwerfen:
"Probieren geht über Studieren"
Schreib doch also einen kleinen Benchmark.
Na, wenn du meinst:
stdafx.h
C:
// stdafx.h : Includedatei für Standardsystem-Includedateien
// oder häufig verwendete projektspezifische Includedateien,
// die nur in unregelmäßigen Abständen geändert werden.
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <time.h>

// TODO: Hier auf zusätzliche Header, die das Programm erfordert, verweisen.
MemoryTest.cpp
C:
// MemoryTest.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//

#include "stdafx.h"


int main(int argc, char* argv[])
{
	size_t ticksT11a = 0;
	size_t ticksT11b = 0;
	size_t ticksT12a = 0;
	size_t ticksT12b = 0;
	size_t ticksT13a = 0;
	size_t ticksT13b = 0;
	size_t ticksT14a = 0;
	size_t ticksT14b = 0;
	int loops = 0;
	srand(0);
	for(loops = 0;loops<10;loops++)
	{
		printf("\n\nLOOP %d\n",loops);
		printf("Test 1.1: 2 Werte ohne Shifting\n");
		clock_t c_1 = clock();
		BYTE* arr_1 = (BYTE*)malloc(2000000); //2 MB
		if(arr_1 == NULL) return -1;
		for(int i = 0;i<2000000;i+=2)
		{
			arr_1[i] = rand()%16;
			arr_1[i+1] = rand()%16;
		}
		ticksT11a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<2000000;i+=2)
		{
			BYTE b1 = arr_1[i];
			BYTE b2 = arr_1[i+1];
		}
		ticksT11b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
	
		free(arr_1);
		printf("Test 1.2: 2 Werte mit Shifting\n");
		c_1 = clock();
		arr_1 = (BYTE*)malloc(1000000); //1 MB
		if(arr_1 == NULL) return -2;
	
		for(int i = 0;i<1000000;i++)
		{
			BYTE b1 = rand()%16;
			BYTE b2 = rand()%16;
			arr_1[i] = b2 | (b1 << 4);
		}
		ticksT12a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<1000000;i++)
		{
			BYTE b1 = arr_1[i] >> 4;
			BYTE b2 = arr_1[i] ^ (b1 << 4);
		}
		ticksT12b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
		free(arr_1);

		printf("Test 1.3: 2 Werte ohne Shifting, 10x groesser\n");
		c_1 = clock();
		arr_1 = (BYTE*)malloc(20000000); //2 MB
		if(arr_1 == NULL) return -1;
		for(int i = 0;i<20000000;i+=2)
		{
			arr_1[i] = rand()%16;
			arr_1[i+1] = rand()%16;
		}
		ticksT13a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<20000000;i+=2)
		{
			BYTE b1 = arr_1[i];
			BYTE b2 = arr_1[i+1];
		}
		ticksT13b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
	
		free(arr_1);
		printf("Test 1.4: 2 Werte mit Shifting, 10x groesser\n");
		c_1 = clock();
		arr_1 = (BYTE*)malloc(10000000); //10 MB
		if(arr_1 == NULL) return -2;
	
		for(int i = 0;i<10000000;i++)
		{
			BYTE b1 = rand()%16;
			BYTE b2 = rand()%16;
			arr_1[i] = b2 | (b1 << 4);
		}
		ticksT14a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<10000000;i++)
		{
			BYTE b1 = arr_1[i] >> 4;
			BYTE b2 = arr_1[i] ^ (b1 << 4);
		}
		ticksT14b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
		free(arr_1);
	}

	printf("\n\n\t\tSUMMARY\n"
		"Total ticks Test 1.1: %d\n"
		"\t1.1a: %d\n"
		"\t1.1b: %d\n"
		"Total ticks Test 1.2: %d\n"
		"\t1.2a: %d\n"
		"\t1.2b: %d\n"
		"Total ticks Test 1.3: %d\n"
		"\t1.3a: %d\n"
		"\t1.3b: %d\n"
		"Total ticks Test 1.4: %d\n"
		"\t1.4a: %d\n"
		"\t1.4b: %d\n",ticksT11a+ticksT11b,ticksT11a,ticksT11b,ticksT12a+ticksT12b,ticksT12a,ticksT12b,ticksT13a+ticksT13b,ticksT13a,ticksT13b,ticksT14a+ticksT14b,ticksT14a,ticksT14b);
	printf("\n\n\t\tAVERAGE\n"
		"1.1: %d\n"
		"1.2: %d\n"
		"1.3: %d\n"
		"1.4: %d\n", (ticksT11a+ticksT11b)/loops, (ticksT12a+ticksT12b)/loops, (ticksT13a+ticksT13b)/loops, (ticksT14a+ticksT14b)/loops);

	system("PAUSE");
	return 0;
}
Falls ich irgendeinen Bullshit geschrieben habe: ComFreek hat mich dazu angestiftet! ;-)

Unter meiner lahmen Ente führt das zu folgendem Ergebnis:
Code:
                SUMMARY
Total ticks Test 1.1: 935
        1.1a: 872
        1.1b: 63
Total ticks Test 1.2: 952
        1.2a: 843
        1.2b: 109
Total ticks Test 1.3: 10516
        1.3a: 9718
        1.3b: 798
Total ticks Test 1.4: 10889
        1.4a: 9922
        1.4b: 967


                AVERAGE
1.1: 93
1.2: 95
1.3: 1051
1.4: 1088
Wie erwartet, dauert die Bitwise-Variante etwas länger. (Hier mit VSC++ 2010 und /Od (keine Optimierung))
Wenn jemand Fehler oder Unreinheiten im Code findet (mal abgesehen von der Redundanz): Immer her damit.

Nun: Was haltet ihr von den Ergebnissen? Würdet ihr die wenigen clockticks Verlust in Kauf nehmen, um die Hälfte des RAMs zu sparen?

Gruss
cwriter

/EDIT:
Hier noch der 4/5 Byte-Vergleich (Kommentare und Beschreibungen stimmen nicht)
C:
void Test2()
{
	size_t ticksT11a = 0;
	size_t ticksT11b = 0;
	size_t ticksT12a = 0;
	size_t ticksT12b = 0;
	size_t ticksT13a = 0;
	size_t ticksT13b = 0;
	size_t ticksT14a = 0;
	size_t ticksT14b = 0;
	int loops = 0;
	srand(0);
	for(loops = 0;loops<10;loops++)
	{
		printf("\n\nLOOP %d\n",loops);
		printf("Test 1.1: 2 Werte ohne Shifting\n");
		clock_t c_1 = clock();
		BYTE* arr_1 = (BYTE*)malloc(5000000); //2 MB
		if(arr_1 == NULL) return;
		for(int i = 0;i<5000000;i+=5)
		{
			arr_1[i] = rand()%256;
			arr_1[i+1] = rand()%256;
			arr_1[i+2] = rand()%256;
			arr_1[i+3] = rand()%16;
			arr_1[i+4] = rand()%16;
		}
		ticksT11a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<5000000;i+=5)
		{
			BYTE b1 = arr_1[i];
			BYTE b2 = arr_1[i+1];
			BYTE b3 = arr_1[i+2];
			BYTE b4 = arr_1[i+3];
			BYTE b5 = arr_1[i+4];
		}
		ticksT11b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
	
		free(arr_1);
		printf("Test 1.2: 2 Werte mit Shifting\n");
		c_1 = clock();
		arr_1 = (BYTE*)malloc(4000000); //1 MB
		if(arr_1 == NULL) return;
	
		for(int i = 0;i<4000000;i+=4)
		{
			arr_1[i] = rand()%256;
			arr_1[i+1] = rand()%256;
			arr_1[i+2] = rand()%256;
			BYTE b1 = rand()%16;
			BYTE b2 = rand()%16;
			arr_1[i+3] = b2 | (b1 << 4);
		}
		ticksT12a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<4000000;i+=4)
		{
			BYTE b1 = arr_1[i];
			BYTE b2 = arr_1[i+1];
			BYTE b3 = arr_1[i+2];
			BYTE b4 = arr_1[i] >> 4;
			BYTE b5 = arr_1[i] ^ (b1 << 4);
		}
		ticksT12b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
		free(arr_1);

		printf("Test 1.3: 2 Werte ohne Shifting, 10x groesser\n");
		c_1 = clock();
		arr_1 = (BYTE*)malloc(50000000); //50 MB
		if(arr_1 == NULL) return;
		for(int i = 0;i<50000000;i+=5)
		{
			arr_1[i] = rand()%256;
			arr_1[i+1] = rand()%256;
			arr_1[i+2] = rand()%256;
			arr_1[i+3] = rand()%16;
			arr_1[i+4] = rand()%16;
		}
		ticksT13a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<50000000;i+=5)
		{
			BYTE b1 = arr_1[i];
			BYTE b2 = arr_1[i+1];
			BYTE b3 = arr_1[i+2];
			BYTE b4 = arr_1[i+3];
			BYTE b5 = arr_1[i+4];
		}
		ticksT13b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
	
		free(arr_1);
		printf("Test 1.4: 2 Werte mit Shifting, 10x groesser\n");
		c_1 = clock();
		arr_1 = (BYTE*)malloc(40000000); //40 MB
		if(arr_1 == NULL) return;
	
		for(int i = 0;i<40000000;i+=4)
		{
			arr_1[i] = rand()%256;
			arr_1[i+1] = rand()%256;
			arr_1[i+2] = rand()%256;
			BYTE b1 = rand()%16;
			BYTE b2 = rand()%16;
			arr_1[i+3] = b2 | (b1 << 4);
		}
		ticksT14a += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array zu beladen.\n",clock()-c_1);
		c_1 = clock();
		for(int i = 0;i<40000000;i+=4)
		{
			BYTE b1 = arr_1[i];
			BYTE b2 = arr_1[i+1];
			BYTE b3 = arr_1[i+2];
			BYTE b4 = arr_1[i] >> 4;
			BYTE b5 = arr_1[i] ^ (b1 << 4);
		}
		ticksT14b += clock()-c_1;
		printf("%d clock ticks sind vergangen, um den Array auszulesen.\n",clock()-c_1);
		free(arr_1);
	}

	printf("\n\n\t\tSUMMARY\n"
		"Total ticks Test 1.1: %d\n"
		"\t1.1a: %d\n"
		"\t1.1b: %d\n"
		"Total ticks Test 1.2: %d\n"
		"\t1.2a: %d\n"
		"\t1.2b: %d\n"
		"Total ticks Test 1.3: %d\n"
		"\t1.3a: %d\n"
		"\t1.3b: %d\n"
		"Total ticks Test 1.4: %d\n"
		"\t1.4a: %d\n"
		"\t1.4b: %d\n",ticksT11a+ticksT11b,ticksT11a,ticksT11b,ticksT12a+ticksT12b,ticksT12a,ticksT12b,ticksT13a+ticksT13b,ticksT13a,ticksT13b,ticksT14a+ticksT14b,ticksT14a,ticksT14b);
	printf("\n\n\t\tAVERAGE\n"
		"1.1: %d\n"
		"1.2: %d\n"
		"1.3: %d\n"
		"1.4: %d\n", (ticksT11a+ticksT11b)/loops, (ticksT12a+ticksT12b)/loops, (ticksT13a+ticksT13b)/loops, (ticksT14a+ticksT14b)/loops);


}

Und das Ergebnis auf meinem Rechner:
Code:
                SUMMARY
Total ticks Test 1.1: 2587
        1.1a: 2433
        1.1b: 154
Total ticks Test 1.2: 2669
        1.2a: 2511
        1.2b: 158
Total ticks Test 1.3: 26612
        1.3a: 25223
        1.3b: 1389
Total ticks Test 1.4: 26705
        1.4a: 25047
        1.4b: 1658


                AVERAGE
1.1: 258
1.2: 266
1.3: 2661
1.4: 2670

Die Differenzen schrumpfen beide.
 
Zuletzt bearbeitet:
Zurück