Ich verwende Cython für die schnelle parallele Verarbeitung von Daten, Hinzufügen von Elementen zu einer gemeinsamen Speicher verknüpften Liste aus mehreren Threads. Ich benutze __sync_bool_compare_and_swap, das eine atomare Vergleichs- und Auslagerungsoperation (CAS) zum Vergleichen bietet, wenn der Wert nicht geändert wurde (durch einen anderen Thread), bevor er durch einen neuen Wert ersetzt wurde.__sync_bool_compare_and_swap mit verschiedenen Parametertypen in Cython
cdef extern int __sync_bool_compare_and_swap (void **ptr, void *oldval, void *newval) nogil
cdef bint firstAttempt = 1
cdef type *next = NULL
cdef type *newlink = ....
while firstAttempt or not __sync_bool_compare_and_swap(<void**> c, <void*>next, <void*>newlink):
firstAttempt = 0
next = c[0]
newlink.next = next
Das funktioniert sehr gut. Jetzt möchte ich aber auch die Größe der verknüpften Liste verfolgen und die gleiche CAS-Funktion für die Updates verwenden, diesmal sind es jedoch keine Zeiger, die aktualisiert werden müssen, sondern ein int. Wie kann dieselbe externe Funktion zweimal in Cython verwendet werden, einmal mit void ** -Parameter und einmal mit einem int * -Parameter?
EDIT
Was ich im Sinn haben zwei getrennte atomare Operationen ist, in einer atomaren Operation ich die verknüpfte Liste aktualisieren möchten, in der anderen möchte ich die Größe aktualisieren. Sie können es in C tun, aber für Cython bedeutet es, dass Sie die gleiche externe Funktion zweimal mit verschiedenen Parametern referenzieren müssen, ist das möglich?
FAZIT
Die Antwort von DavidW vorgeschlagen arbeitet. Falls jemand eine ähnliche Konstruktion verwendet, sollten Sie beachten, dass bei der Verwendung von zwei separaten Update-Funktionen keine Garantie besteht, dass diese nacheinander verarbeitet werden (dh ein anderer Thread kann dazwischen aktualisieren), wenn das Ziel ist, ein Update durchzuführen B. zur Überwachung des Fortschritts während des Multithreading oder zur Erstellung eines aggregierten Ergebnisses, das erst nach Beendigung aller Threads verwendet wird, garantiert CAS, dass alle Updates genau einmal ausgeführt werden. Unerwarteterweise verweigert gcc die Kompilierung, ohne in void * umzuwandeln, also entweder separate hard-typed-Versionen zu definieren, oder Sie müssen casten. Ein Ausschnitt aus meinem Code:
in some_header.h:
#define sync_bool_compare_and_swap_int __sync_bool_compare_and_swap
#define sync_bool_compare_and_swap_vp __sync_bool_compare_and_swap
in some_prog.pxd:
cdef extern from "some_header.h":
cdef extern int sync_bool_compare_and_swap_vp (void **ptr, void *oldval, void *newval) nogil
cdef extern int sync_bool_compare_and_swap_int (int *ptr, int oldval, int newval) nogil
in some_prog.pyx:
cdef void updateInt(int *value, int incr) nogil:
cdef cINT previous = value[0]
cdef cINT updated = previous + incr
while not sync_bool_compare_and_swap_int(c, previous, updated):
previous = value[0]
updated = previous + incr
Das auf eine Sperre verzichten, wenn die Daten konsistent sein sollen. das würde beinhalten, atomare Daten an zwei völlig verschiedenen Speicherorten zu ändern. Es scheint aber nicht so, als ob es irgendwie nützlich wäre. Was ist dein tatsächlicher Anwendungsfall? – Voo
@ Voo hinzugefügt einige Klarheit der Frage, das können zwei separate atomare Operationen sein, das Problem ist, wie die gleiche externe Funktion zweimal in Cython mit verschiedenen Parametern zu referenzieren? –
Fair genug, das Problem ist, dass diese nicht wirklich "Funktionen" sind. Sie sind Einbauten, die sich ähnlich wie eine Funktion verhalten. Ich sehe nur die zwei offensichtlichen Problemumgehungen: Verknüpfen Sie eine c-DLL, die die Aufrufe weiterleitet, oder fügen Sie die Definitionen in separate Module ein. – Voo