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

Cython中是否有类似reinterpret_cast的机制?实现无类型内存视图快速强转

Cython中numpy结构化数组的高效内存视图复用与类型重解释方案

一、先解决核心性能问题:避免重复创建内存视图

你的代码性能差的根本原因是每次循环都重复将numpy数组转换为内存视图,这一步涉及类型检查、内存布局验证等开销,100万次重复会导致严重性能损耗。只需要把内存视图的创建移到循环外,就能直接解决性能问题:

%%cython -a

cimport numpy as cnp
import numpy as np
from time import time

cdef packed struct Bar:
    cnp.int64_t dt
    double open
    double high
    double low
    double close
    cnp.int64_t volume

bar_dtype = np.dtype([('dt', 'i8'), ('open', 'f8'), ('high', 'f8'), ('low', 'f8'), ('close', 'f8'), ('volume', 'i8')])

cpdef f(Bar bar):
    cdef cnp.ndarray bars_sar
    cdef Bar[:] buffer
    
    bars_sar = np.empty((1000000,), dtype=bar_dtype)
    buffer = bars_sar  # 仅转换一次内存视图,移至循环外
    
    start = time()
    for n in range(1000000):
        buffer[0] = bar  # 循环内直接复用已创建的内存视图
        
    print(f'Elapsed: {time() - start}')
    return buffer

def test():
    sar = f(Bar(1,2,3,4,5,6))
    print(sar[0])
    return sar

修改后循环耗时会降至毫秒级,完全解决性能问题。

二、实现类似C语言reinterpret_cast的类型重解释

如果确实需要将内存以无类型形式存储,之后再重新解释为特定类型的内存视图,Cython提供两种可行方案:

方案1:通过numpy数组的底层指针实现类型重解释

直接获取numpy数组的data指针(无类型void*),需要访问时再强制转换为目标类型的内存视图:

cpdef f_reinterpret(Bar bar):
    cdef cnp.ndarray bars_sar
    cdef void* raw_ptr
    cdef Bar[:] buffer
    
    bars_sar = np.empty((1000000,), dtype=bar_dtype)
    raw_ptr = <void*>bars_sar.data  # 存储无类型指针
    
    # 需要访问时,将无类型指针转换为Bar类型的内存视图
    buffer = <Bar[:bars_sar.shape[0]]>raw_ptr
    
    start = time()
    for n in range(1000000):
        buffer[0] = bar
        
    print(f'Elapsed (reinterpret): {time() - start}')
    return buffer

方案2:直接用C指针操作(更接近C的reinterpret_cast)

如果追求极致性能,可以直接用C指针进行内存操作,跳过内存视图的封装:

cpdef f_raw_ptr(Bar bar):
    cdef cnp.ndarray bars_sar
    cdef Bar* bar_ptr
    
    bars_sar = np.empty((1000000,), dtype=bar_dtype)
    bar_ptr = <Bar*>bars_sar.data  # 直接转换为Bar类型指针
    
    start = time()
    for n in range(1000000):
        bar_ptr[0] = bar  # 直接通过指针访问内存
        
    print(f'Elapsed (raw ptr): {time() - start}')
    # 可选:转换回内存视图返回
    return <Bar[:bars_sar.shape[0]]>bar_ptr

三、关于你尝试的错误说明

你之前直接转换内存视图到void*失败,是因为内存视图(Bar[:])是Cython的封装类型,不是原始指针,不能直接转换或取地址。正确的做法是从numpy数组或内存视图的data属性获取底层原始指针,再进行类型转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:45:47