gpt4 book ai didi

multithreading - __sync_bool_compare_and_swap 在 Cython 中具有不同的参数类型

转载 作者:行者123 更新时间:2023-12-04 06:45:10 25 4
gpt4 key购买 nike

我正在使用 Cython 进行数据的快速并行处理,将项目从多个线程添加到共享内存链表。我使用 __sync_bool_compare_and_swap,它提供了一个原子比较和交换 (CAS) 操作来比较该值是否在用新值替换之前未被修改(由另一个线程)。

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

这非常有效。但是,现在我也想跟踪链表的大小,并希望使用相同的 CAS 函数进行更新,但是,这次需要更新的不是指针而是 int。如何在 Cython 中两次使用相同的外部函数,一次使用 void** 参数,一次使用 int* 参数?

编辑

我想到的是两个独立的原子操作,一个原子操作我想更新链表,另一个我想更新大小。您可以在 C 中执行此操作,但对于 Cython 而言,这意味着您必须使用不同的参数两次引用相同的外部函数,可以做到吗?

结论

DavidW 建议的答案有效。如果有人想使用类似的结构,您应该意识到,当使用两个单独的更新函数时,不能保证按顺序处理它们(即另一个线程可以在两者之间进行更新),但是,如果目标是更新一个累积值,例如在多线程时监控进度或创建一个聚合结果,直到所有线程完成后才使用,CAS 确实保证所有更新都只完成一次。出乎意料的是,gcc 拒绝在不强制转换为 void* 的情况下进行编译,因此要么定义单独的硬类型版本,要么需要强制转换。我的代码片段:

在 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

在 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

在 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

最佳答案

所以问题(据我所知)是 __sync_bool_compare_and_swap是一个内在的编译器而不是一个函数,所以实际上并没有固定的签名,因为编译器只是计算出来的。但是,Cython 要求知道类型,并且因为您想将它用于两种不同的类型,所以您遇到了问题。

我看不到比诉诸(非常)少量的 C 来“帮助”Cython 更简单的方法。用一堆 #defines 创建一个头文件

/* compare_swap.h */
#define sync_bool_compare_swap_voidp __sync_bool_compare_and_swap
#define sync_bool_compare_swap_int __sync_bool_compare_and_swap

然后你可以告诉 Cython 这些都是一个单独的函数
cdef extern from "compare_swap.h":
int sync_bool_compare_swap_voidp(void**, void*, void*)
int sync_bool_compare_swap_int(int*, int, int)

在这个阶段,您应该能够自然地将它们用作普通函数,而无需进行任何类型转换(即代码中没有 <void**>,因为这往往会隐藏真正的错误)。 C 预处理器将生成您想要的代码,一切正常。

编辑 :几年后看这个,我可以看到一些你可能会使用的更简单的方法(未经测试,但我不明白为什么它们不应该工作)。首先,您可以使用 Cython 将名称映射到“cname”的功能,以避免需要额外的 header :
cdef extern from *:
int sync_bool_compare_swap_voidp(void**, void*, void*) "__sync_bool_compare_and_swap"
int sync_bool_compare_swap_int(int*, int, int) "__sync_bool_compare_and_swap"

其次(可能是最好的)您可以使用单个通用定义(只是告诉 Cython 它是一个可变参数函数):
cdef extern from "compare_swap.h":
int __sync_bool_compare_and_swap(...)

这样,Cython 就不会试图理解所使用的类型,而只会将其完全交给 C(这就是您想要的)。

我不想评论您使用这样的两个原子操作是否安全,或者这是否会通过具有危险的不一致数据的状态......

关于multithreading - __sync_bool_compare_and_swap 在 Cython 中具有不同的参数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37186861/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com