看起来你在这里很迂回。这不会做同样的事情吗?
output = np.frombuffer(data,'b').reshape(-1,3)[:,1:].flatten().view('i2')
这将节省一些时间,因为它不会对临时数组进行零填充、跳过位移位并避免一些不必要的数据移动。不过,我实际上还没有对它进行基准测试,而且我预计节省的费用是适度的。
编辑:我现在已经执行了基准测试。对于len(data)
1200 万,我的版本为 80 毫秒,我的版本为 39 毫秒,因此几乎是 2 倍的加速。正如预期的那样,没有很大的改进,但你的起点已经相当快了。
Edit2:我应该提到我在这里假设了小端。但是,原始问题的代码也隐含地假设小端,所以这不是我的新假设。
(对于大端序(数据和架构),您将替换1:
为:-1
。如果数据的字节序与 CPU 不同,那么您还需要反转字节顺序 ( ::-1
)。)
Edit3:为了更快的速度,我认为你将不得不去 python 之外。与我的版本相比,这个也使用 openMP 的 fortran 函数使我的速度提高了 2 倍以上(比你的版本快 4 倍以上)。
subroutine f(a,b)
implicit none
integer*1, intent(in) :: a(:)
integer*1, intent(out) :: b(size(a)*2/3)
integer :: i
!$omp parallel do
do i = 1, size(a)/3
b(2*(i-1)+1) = a(3*(i-1)+2)
b(2*(i-1)+2) = a(3*(i-1)+3)
end do
!$omp end parallel do
end subroutine
用 编译FOPT="-fopenmp" f2py -c -m basj{,.f90} -lgomp
。然后你可以在 python 中导入和使用它:
import basj
def convert(data): return def mine2(data): return basj.f(np.frombuffer(data,'b')).view('i2')
您可以通过环境变量控制要使用的核心数量OMP_NUM_THREADS
,但它默认使用所有可用的核心。