概述
有一些问题与此类似,但它们都略有不同。要明确的是,如果values
是一个整数数组,我想找到perm
,使sorted_values
(values
按某个比较运算符排序),由
sorted_values[i] = values[perm[i]]
第1步
如何在C中执行此操作?好qsort
需要声明一个比较函数来告诉你一个值是否大于另一个值。如果我们使values
成为全局变量,那么我们可以利用这个比较函数对最初设置为perm
的数组0:N-1
进行排序(其中N
是{{1}的长度不比较values
与perm[i]
,而是比较perm[j]
与values[perm[i]]
。见link。一些示例C代码:
values[perm[j]]
当然,诀窍在于全局定义// sort_test.c
#include <stdio.h>
#include <stdlib.h>
int *values;
int cmpfunc (const void * a, const void * b) {
return ( values[*(int*)a] - values[*(int*)b] );
}
int main () {
int i;
int n = 5;
int *perm;
// Assign memory
values = (int *) malloc(n*sizeof(int));
perm = (int *) malloc(n*sizeof(int));
// Set values to random values between 0 and 99
for (i=0; i<n; i++) values[i] = rand() % 100;
// Set perm initially to 0:n-1
for (i=0; i<n; i++) perm[i] = i;
printf("Before sorting the list is: \n");
for (i=0; i<n; i++) printf("%d ", values[i]);
qsort(perm, n, sizeof(int), cmpfunc);
printf("\nThe sorting permutation is: \n");
for (i=0; i<n; i++) printf("%d ", perm[i]);
free(values);
free(perm);
printf("\n");
return(0);
}
,因此values
可以看到它。
第2步
如何在Cython中完成?不幸的是,我不能让Cython使用与全局声明的值相同的技巧。我最好的尝试是基于答案here的以下内容,但不同之处在于它们只是排序他们不需要获取索引/排列的数组。
cmpfunc
可以使用
编译# sort_test_c.pyx
cimport cython
from libc.stdlib cimport qsort
# Try declaring global variable for the sort function
cpdef long[:] values
cdef int cmpfunc (const void *a , const void *b) nogil:
cdef long a_v = (<long *> a)[0]
cdef long b_v = (<long *> b)[0]
return (values[a_v] - values[b_v]);
def sort(long[:] py_values, long[:] perm, int N):
# Assign to global
values = py_values
# Make sure perm is 0:N-1
for i in range(N):
perm[i] = i
# Perform sort
qsort(&perm[0], N, perm.strides[0], &cmpfunc)
并使用脚本进行测试
cythonize -i sort_test_c.pyx
然而,这引起了我们的全局变量# sort_test.py
from sort_test_c import sort
import numpy as np
n = 5
values = np.random.randint(0, 100, n).astype(int)
perm = np.empty(n).astype(int)
sort(values, perm, n)
,即
values
并且排序排列不正确(除非UnboundLocalError: local variable 'values' referenced before assignment
Exception ignored in: 'sort_test_c.cmpfunc
已经被排序,在这种情况下幸运,因为values
总是返回数组perm
)。我该如何解决这个问题?