Setzen Sie ein int (16 Bit) Array auf den maximalen Wert von short

7

Ich finde die Antwort darauf nirgends, Wie speichere ich ein Array auf den maximalen Wert des Array-Typs? Ich hätte gedacht, dass memset(ZBUFFER,0xFFFF,size) funktionieren würde, wo ZBUFFER ein 16-Bit Integer-Array ist. Stattdessen bekomme ich -1s durch.

Die Idee ist auch, dass das so schnell wie möglich funktioniert (es ist ein zbuffer, der jeden Frame initialisieren muss). Wenn es einen besseren Weg gibt (und immer noch so schnell oder schneller), lass es mich wissen.

>

bearbeiten: Zur Klarstellung brauche ich ein int-Array mit Vorzeichen.

    
slicedtoad 11.04.2013, 11:46
quelle

9 Antworten

9

In C ++ würden Sie std :: fill und std :: numeric_limits verwenden.

%Vor%

Dies funktioniert mit jedem Typ.

In C sollten Sie memset , das den Wert von Bytes festlegt, nicht beibehalten. Um ein Array anderer Typen als char (ev.% Co_de%) zu initialisieren, müssen Sie auf eine manuelle unsigned -Schleife zurückgreifen.

    
Didier Trosset 11.04.2013, 11:58
quelle
7

-1 und 0xFFFF sind das Gleiche in einer 16-Bit-Ganzzahl unter Verwendung einer Zweierkomplementdarstellung. Sie erhalten nur -1, weil Sie entweder Ihr Array als short anstatt als unsigned short deklariert haben. Oder weil Sie die Werte bei der Ausgabe in signed umwandeln.

Übrigens ist Ihre Annahme falsch, dass Sie außer bytes mit memset etwas einstellen können. memset(ZBUFFER, 0xFF, size) hätte das Gleiche gemacht.

    
john 11.04.2013 11:49
quelle
4

In C ++ können Sie ein Array mit einem Wert mit dem Algorithmus std::fill füllen.

%Vor%

Dies ist weder schneller noch langsamer als Ihr aktueller Ansatz. Es hat jedoch den Vorteil, zu arbeiten.

    
R. Martinho Fernandes 11.04.2013 11:59
quelle
3

Geschwindigkeit nicht der Sprache zuordnen. Das ist für Implementierungen von C. Es gibt C-Compiler, die schnellen, optimalen Maschinencode und C-Compiler erzeugen, die langsamen, nicht optimalen Maschinencode erzeugen. Genauso für C ++. Eine "schnelle, optimale" Implementierung könnte Code optimieren, der langsam erscheint . Daher macht es keinen Sinn, eine Lösung schneller zu nennen als eine andere. Ich werde über die Korrektheit sprechen und dann über Leistung sprechen, egal wie unbedeutend es ist. Es wäre eine bessere Idee, Ihren Code zu profilieren, um sicherzugehen, dass dies tatsächlich der Flaschenhals ist, aber machen wir weiter.

Betrachten wir zuerst die sinnvollste Option: Eine Schleife, die int -Werte kopiert. Durch das Lesen des Codes wird klar, dass die Schleife SHRT_MAX korrekt jedem int -Element zuweist. Sie können unten einen Testfall dieser Schleife sehen, der versucht, das größtmögliche Array zu verwenden, das zu der Zeit von malloc zugewiesen werden kann.

%Vor%

Ich habe dies auf meinem System ausgeführt, das mit verschiedenen aktivierten Optimierungen kompiliert wurde ( -O3 -march=core2 -funroll-loops ). Hier ist die Ausgabe:

%Vor%

Beachten Sie die "Ausführungszeit" ... Das ist ziemlich schnell! Wenn überhaupt, ist der Flaschenhals hier die Cache-Lokalität eines so großen Arrays, weshalb ein guter Programmierer versuchen wird, Systeme zu entwerfen, die nicht so viel Speicher verbrauchen ... Nun, dann betrachten wir die Option memset. Hier ist ein Zitat aus dem Memset-Handbuch :

  

Die Funktion memset () kopiert c (umgewandelt in ein unsigned char ) in   jedes der ersten n Bytes des Objekts, auf das s zeigt.

Daher konvertiert es 0xFFFF in ein unsigniertes Zeichen (und kürzt möglicherweise diesen Wert) und weist dann den konvertierten Wert den ersten size Bytes zu. Dies führt zu einem falschen Verhalten. Ich mag es nicht, sich darauf zu verlassen, dass der Wert SHRT_MAX als eine Folge von Bytes dargestellt wird, die den Wert (unsigned char) 0xFFFF speichern, da dies auf Übereinstimmung beruht. Mit anderen Worten, das Hauptproblem ist hier, dass memset für Ihre Aufgabe nicht geeignet ist. Benutze es nicht. Nachdem dies gesagt wurde, ist hier ein Test, abgeleitet von dem obigen Test, der verwendet wird, um die Geschwindigkeit von memset zu testen:

%Vor%

Eine triviale byte-kopierende memset-Schleife iteriert sizeof (int) mal mehr als die Schleife in meinem ersten Beispiel. Wenn man bedenkt, dass meine Implementierung ein ziemlich optimales memset verwendet, ist hier die Ausgabe:

%Vor%

Diese Tests werden wahrscheinlich sehr unterschiedlich ausfallen. Ich habe sie nur einmal ausgeführt, um eine ungefähre Vorstellung zu bekommen. Hoffentlich sind Sie zu der gleichen Schlussfolgerung gekommen, die ich habe: Häufige Compiler sind ziemlich gut darin, einfache Schleifen zu optimieren, und es ist nicht wert, hier über Mikrooptimierungen nachzutragen.

Zusammenfassend:

  1. Verwenden Sie memset nicht zum Füllen von Ints mit Werten (mit Ausnahme für den Wert 0), da dies nicht geeignet ist.
  2. Fordern Sie keine Optimierungen vor dem Ausführen von Tests auf. Führen Sie keine Tests durch, bis Sie eine funktionierende Lösung haben. Mit Arbeitslösung meine ich "Ein Programm, das ein tatsächliches Problem löst". Sobald Sie das haben, verwenden Sie Ihren Profiler, um weitere Optimierungschancen zu identifizieren!
Sebivor 11.04.2013 15:31
quelle
2

Dies liegt an Zweierkomplement . Sie müssen Ihren Array-Typ in unsigned short ändern, um den maximalen Wert zu erhalten, oder 0x7FFF verwenden.

    
Carsten 11.04.2013 11:49
quelle
2
%Vor%

Beachten Sie, dass dies die letzten paar Bytes, if (SIZE % sizeof(short))

, nicht initialisiert     
Adrian Panasiuk 11.04.2013 11:58
quelle
2

In C kannst du es wie Adrian Panasiuk machen, und du kannst auch die Kopierschleife ausrollen. Das Abrollen bedeutet, dass größere Stücke gleichzeitig kopiert werden. Das äußerste Ende des Loop-Abrollvorgangs kopiert den gesamten Frame mit einem Null-Frame wie folgt:

%Vor%

tatsächliches Löschen:

%Vor%

(Sie können mit verschiedenen Größen des leeren ZBUFFER experimentieren, ab vier Bytes und dann eine Schleife um das Memcpy herum.)

Wie immer testen Sie Ihre Ergebnisse, wenn a) es sich lohnt, diesen Teil des Programms zu optimieren und b) welchen Unterschied die verschiedenen Initialisierungstechniken machen. Es hängt von vielen Faktoren ab. Für die letzten paar Prozent der Leistung müssen Sie möglicherweise auf Assembler-Code zurückgreifen.

    
Prof. Falken 11.04.2013 13:34
quelle
0
%Vor%

wobei FOO der Typ von ZBUFFER s Elementen ist.

    
fizzer 11.04.2013 12:01
quelle
0

Wenn Sie "memset" sagen, müssen Sie diese Funktion tatsächlich verwenden? Das ist nur eine byteweise Zuweisung, so dass es nicht mit vorzeichenbehafteten Arrays funktioniert.

Wenn Sie jeden Wert auf den Maximalwert setzen möchten, verwenden Sie beispielsweise:

std::fill( ZBUFFER, ZBUFFER+len, std::numeric_limits<short>::max() )

wenn len die Anzahl der Elemente ist (nicht die Größe in Bytes Ihres Arrays)

    
CashCow 11.04.2013 12:01
quelle

Tags und Links