You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cython中如何安全检测malloc分配的memoryview元素是否已赋值?

问题:malloc分配的内存中安全检测已赋值元素的方法

我希望在函数中临时创建多个小型memoryview,并在函数结束时释放它们。根据对比,使用malloc初始化memoryview性能更优、速度更快,但这些小型memoryview中仅有部分元素被赋值,请问安全检测元素是否已赋值的方法是什么?

代码与性能对比

以下是使用malloc和numpy ndarray实现的代码及性能对比:

## test_malloc.pyx

cimport cython
import numpy as np
cimport numpy as np

from libc.stdlib cimport malloc, free

np.import_array()


@cython.wraparound(False)
@cython.boundscheck(False)
cdef int _num_assign_malloc():
    cdef:
        Py_ssize_t n = 50
        double *x = <double *> malloc(n * sizeof(double))
        Py_ssize_t i
        int k = 0

    x[5] = 1.
    x[8] = 1.
    x[38] = 1.

    for i in range(n):
        if x[i] == 1.:
            k += 1

    free(x)
    return k


@cython.wraparound(False)
@cython.boundscheck(False)
cdef int _num_assign_ndarray():
    cdef:
        Py_ssize_t n = 50
        double[::1] x = np.zeros(n, dtype=np.float64)
        Py_ssize_t i
        int k = 0

    x[5] = 1.
    x[8] = 1.
    x[38] = 1.

    for i in range(n):
        if x[i] == 1.:
            k += 1

    return k


cpdef test_num_malloc():
    return _num_assign_malloc()


cpdef test_num_ndarray():
    return _num_assign_ndarray()

timeit测试结果:

>>> import timeit
>>> t = timeit.Timer("from test_malloc import test_num_malloc; test_num_malloc()")
>>> t.timeit(10000)
# 0.0111
>>> t = timeit.Timer("from test_malloc import test_num_ndarray; test_num_ndarray()")
>>> t.timeit(10000)
# 0.0246

未赋值元素的随机值问题

当查看malloc分配的内存中未赋值元素时,编写如下测试代码:

@cython.wraparound(False)
@cython.boundscheck(False)
cdef _malloc_unassign():
    cdef:
        Py_ssize_t n = 20
        double *x = <double *> malloc(n * sizeof(double))
        double[::1] y = np.zeros(n, dtype=np.float64)
        Py_ssize_t i

    x[5] = 1.
    x[8] = 1.

    for i in range(n):
        y[i] = x[i]

    free(x)
    return y


cpdef test_malloc():
    return _malloc_unassign()

执行后得到结果:

>>> from test_malloc import test_malloc
>>> for t in test_malloc():
...    print(t)
...
    6.230420704259778e-307
    3.5604305343967845e-307
    1.6021930623879718e-306
    2.447635570273665e-307
    1.6911933005114767e-306
    1.0
    1.0570034520433751e-307
    1.2461038328174693e-306
    1.0
    8.066321387750432e-308
    1.201607109425611e-306
    1.691193300407861e-306
    1.2906222865963489e-306
    1.4241722150642528e-306
    1.3351264799003858e-306
    7.56596412080425e-307
    7.565984490202416e-307
    1.6021903463576915e-306
    1.424109743093715e-306
    2.2250738585072396e-306

看起来可以通过x[i] == 1.来检测,但这种方式并不可靠——未赋值元素是随机值,若使用int类型,误判概率会更高。

补充:calloc方案的测试

感谢@DavidW提供的calloc方案,新增代码及性能测试如下:

@cython.boundscheck(False)
@cython.wraparound(False)
cdef int _num_assign_calloc():
    cdef:
        Py_ssize_t n = 50
        double *x = <double *> calloc(n, sizeof(double))
        Py_ssize_t i
        int k = 0

    x[5] = 1.
    x[8] = 1.
    x[38] = 1.

    for i in range(n):
        if x[i] == 1.:
            k += 1

    free(x)
    return k

timeit测试结果:

>>> import numpy as np
>>> time_malloc = []
>>> for i in range(1000):
...     t = timeit.Timer("from core.test_malloc import test_num_malloc; test_num_malloc()")
...     time_malloc.append(t.timeit(10000))
...
...
>>> time_ndarr = []
>>> for i in range(1000):
...     t = timeit.Timer("from core.test_malloc import test_num_ndarray; test_num_ndarray()")
...     time_ndarr.append(t.timeit(10000))
...
...
>>> time_calloc = []
>>> for i in range(1000):
...     t = timeit.Timer("from core.test_malloc import test_num_calloc; test_num_calloc()")
...     time_calloc.append(t.timeit(10000))
...
...
>>> print("mean: %.4f, std: %.4f" % (np.mean(time_malloc), np.std(time_malloc)))
mean: 0.0098, std: 0.0034
>>> print("mean: %.4f, std: %.4f" % (np.mean(time_calloc), np.std(time_calloc)))
mean: 0.0098, std: 0.0026
>>> print("mean: %.4f, std: %.4f" % (np.mean(time_ndarr), np.std(time_ndarr)))
mean: 0.0177, std: 0.0033

内容的提问来源于stack exchange,提问作者Elkan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 11:40:32