PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Python 2x 32 Bit int aus 64 Bit long auspacken


Diapolo
2011-08-17, 13:52:50
Vorweg, ich kenne C und kann mit Python wenig anfangen, habe aber ein Problem, dass ich lösen muss.

- output ist ein ulong Array
- in einem OpenCL Kernel (C) passiert folgendes:

ulong Var = ((ulong)(beliebige uint) << 32) | ((beliebige uint) & 0xFFFFFFFFL);
output[1] = Var;

Nun versuche ich recht verzweifelt in der Hauptanwendung, die in Python geschrieben ist die 2 uints aus der long output zu entpacken.

Dies habe ich versucht über:
for i in xrange(self.OUTPUT_SIZE - 1):
if int(output.item((i + 1)) >> 32):
mach_irgendwas
if int((long(output[i + 1]) & 0xffffffff)):
mach_irgendwas_anderes

Aber das funktioniert nicht bzw. nur für die untere if-Bedingung. Man sieht die 2 ifs unterscheiden sich auch schon massiv, da ich keinen Plan habe wie ichs anstellen kann. Ich habe mich durch Docs gewühlt aber nix gefunden.

output ist zumindest via numPy angelegt worden:
output = np.zeros(self.OUTPUT_SIZE, np.uint64)

Zur HÜLFÄÄÄÄÄÄ! Ich hoff hier gibts Python Götter die mir schnell helfen können :).

Dia

Tiamat
2011-08-17, 15:41:48
Kopier doch bit für bit in zwei variablen mit Schnitt nach je 32 bits

Diapolo
2011-08-17, 16:20:22
Ich habe das nun mal weiter debugged und es sieht so aus, als sei der hi Teil immer 0 (lo funktioniert). Nun ist entweder output nicht 64-Bit lang oder irgendetwas anderes passt nicht.

Hier nochmal der aktuelle Python Code:

for i in xrange(self.OUTPUT_SIZE - 1):
if int(output.item(i) >> 32):
machwas_hi
if int(output.item(i) & 0xffffffff):
machwas_lo

Stimmt da was mit dem uint64 nicht? ARGHL! Kann ich mir irgendwo die Bitlänge eines numpy Objekts ausgeben lassen?

Dia

Nagelbrett
2011-08-17, 17:49:30
hilft dir vielleicht unpack(_from) aus struct weiter?
from struct import *
r = unpack_from('LL', output.item(i))
gibt ein tuple mit den beiden Hälften.

Diapolo
2011-08-17, 19:10:58
hilft dir vielleicht unpack(_from) aus struct weiter?
from struct import *
r = unpack_from('LL', output.item(i))
gibt ein tuple mit den beiden Hälften.

Ein Tuple? Da werd ich dann mal nach googlen, ebenso wie nach unpack_from. Allerdings, so scheint es mir, ist in output.item(i) nur eine 32-Bit Zahl drinnen, obwohl der Datentyp ganz klar uint64 ist ... ich verstehs echt noch nicht.

Kann pyopencl vielleicht nicht mit uint64 ... Fragen über Fragen :-/. Danke dir aber trotzdem!

Dia

pest
2011-08-18, 12:26:50
ich verstehe das problem nicht wirklich?

lass dir den "dtype" des numpy-objektes ausgeben.

Diapolo
2011-08-18, 14:46:05
ich verstehe das problem nicht wirklich?

lass dir den "dtype" des numpy-objektes ausgeben.

Der IST uint64, aber ich bekomme trotzdem keine 2 ints mehr raus :-P DAS ist das Problem. Frage ist doch, stimmt mein Code überhaupt mit dem Bit-Shift und dem AND!?

Dia

pest
2011-08-18, 15:09:58
gib die zahl im ganzen aus, ist da der komplette inhalt sichtbar?

wird wohl irgendwo an nem korrekten cast hängen.


(long(output[i + 1]) & 0xffffffff)


der cast ist überflüssig.

Diapolo
2011-08-18, 16:18:46
gib die zahl im ganzen aus, ist da der komplette inhalt sichtbar?

wird wohl irgendwo an nem korrekten cast hängen.


(long(output[i + 1]) & 0xffffffff)


der cast ist überflüssig.

Da output ein numPy Object ist muss ich entweder mit long() oder int() casten oder via output.item(i) direkt auf das jeweilige Element zugreifen, sonst erhalte ich den Fehler, dass weder & noch >> als Operatoren erlaubt sind. Am OpenCL C-Code sollte das Problem eigentlich nicht liegen, aber irgendwo geht mir was verloren ...

Dia

GMP
2011-08-20, 11:29:17
Warum eigentlich so kompliziert?
Warum kein numpy array aus 32 bit Abschnitten und dann jeden Wert einzeln lesen?
Das ergibt für mich gerade spontan wenig Sinn und sieht eher nach ner Art frühzeitiger Optimierung aus, die ja bekannt ist dafür die Wurzel allen Übels zu sein ;)
Auch sagt die numpy ndarray doku das item() dir wenn möglich ein Python Integer zurück gibt, wenn es die Elemente darauf abbilden kann daher brauchst du auch nix "casten"
http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.item.html#numpy.ndarray.item

Du siehst auch an deinem Code das es das tut
for i in xrange(self.OUTPUT_SIZE - 1):
if int(output.item(i) >> 32):
machwas_hi
if int(output.item(i) & 0xffffffff):
machwas_lo

der int() aufruf passiert ja jeweils auf dem Ergebnis der Bitfummelei und wenn die nicht klappen würde hätte dich Python schon angemeckert.
Auch is xrange(size-1) quatsch wenn du nicht explizit das letzte element deiner Liste auslassen wolltest da der letzte Wert den dir xrange(size) liefert schon size-1 ist.
Wenn du dann eh durch alle Elemente der Liste durch willst ohne dich für den Index zu interessieren
schreibt man in Python eher


for each in output:
if each >> 32:
machwas_hi
if each & 0xffffffff:
machwas_lo

Das ist aber nur ne andere Schreibweise deines Codes (ausser das das letzte Element mitgenommen wird) und der sieht irgendwie richtig aus, daher liegt der fehler wohl im opencl code

ach und übrigens macht int() auch nur 32 Bit große Integer aus anderen Zahlen oder aus nem String, erst long() geht bis unendlich

Diapolo
2011-08-22, 17:37:55
Danke für eure ganzen Tips, der Fehler lag in der Tat auch im OpenCL Code. Und diesen habe ich nun gefunden. Aber die Anregungen von GMP waren auch sehr hilf- und lehrreich :).

Dia