Bas*_*asj 5 python arrays numpy cython timeit
我使用以下代码将24位二进制文件加载data到16位数numpy组中:
temp = numpy.zeros((len(data) / 3, 4), dtype='b')
temp[:, 1:] = numpy.frombuffer(data, dtype='b').reshape(-1, 3)
temp2 = temp.view('<i4').flatten() >> 16 # >> 16 because I need to divide by 2**16 to load my data into 16-bit array, needed for my (audio) application
output = temp2.astype('int16')
Run Code Online (Sandbox Code Playgroud)
我想可以提高速度效率,但是如何?
看来你在这里很迂回。这不会做同样的事情吗?
output = np.frombuffer(data,'b').reshape(-1,3)[:,1:].flatten().view('i2')
Run Code Online (Sandbox Code Playgroud)
这将节省一些时间,因为不会对临时数组进行零填充、跳过位移并避免一些不必要的数据移动。不过,我还没有真正对其进行基准测试,我预计节省的费用不会太多。
编辑:我现在已经执行了基准测试。对于len(data)1200 万,我的版本获得了 80 毫秒的时间,而我的版本获得了 39 毫秒的时间,因此速度几乎达到了 2 倍。正如预期的那样,这并不是一个很大的改进,但你的起点已经相当快了。
Edit2:我应该提到我在这里假设了小端。然而,原始问题的代码也隐式假设小端,所以这对我来说并不是一个新的假设。
(对于大端(数据和体系结构),您将替换1:为:-1。如果数据的端序与 CPU 不同,那么您还需要反转字节的顺序 ( ::-1)。)
Edit3:为了更快的速度,我认为你必须走出Python。这个 fortran 函数也使用 openMP,与我的版本相比,速度提高了 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
Run Code Online (Sandbox Code Playgroud)
编译用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')
Run Code Online (Sandbox Code Playgroud)
您可以通过环境变量控制要使用的核心数量OMP_NUM_THREADS,但默认情况下使用所有可用核心。