Numpy.array较慢的原因以及如何优化它的性能

Numpy.array较慢的原因以及如何优化它的性能

前言

在使用Numpy时,我们经常有一些疑问,例如它的性能为什么不如预期的那么好,代码为什么会显得如此笨拙,这些问题有关于Numpy本身的运作机制。在本文中,我们将深入了解,并分析Numpy.array较慢的原因以及如何优化它的性能。

阅读更多:Numpy 教程

数据类型

在Python中,有许多数据类型,每种数据类型都具有不同的数据存储方式和内存架构。Numpy将数据存储在连续的内存块中,支持一种基本的数据结构:Numpy Array。因为Numpy Array数组包含同一类型的元素,所以才能存储在相同的大小内存块中,并且由于其内存块的连续性,使得它更易于管理和访问数据。

举个例子,从列表中创建数组:

import numpy as np

list = [1, 2, 3, 4]
arr = np.array(list)
Python

以上代码将列表“list”转换为Numpy Array,直接通过切片来获取元素:

print(arr[0:3])
Python

结果将是

[1 2 3]
Python

内存效率

常规的Python列表可能会占用更多的内存,而Numpy对于内存效率的优化则显得十分明显。在列表中,元素可以是不同类型的,但是在Numpy中,每个元素必须是相同的数据类型。这种特殊的数据结构可以对Numpy Array进行内存块优化,实现互相补充、整合使用。

例如,我们可以使用自定义dtype对Numpy Array进行优化:

dt = np.dtype('i4') # i4表示int32类型
arr = np.array([1, 2, 3, 4], dtype=dt)
print(arr)
Python

得到如下结果:

[1 2 3 4]
Python

现在,Numpy Array被指定为整数类型的数据类型,并且占用的内存比Python列表更少。

速度问题

Numpy Array数组是一种非常强大的数据结构,但很多情况下它的执行速度相对较慢。这可能是因为Numpy Array是更高级的数据结构,所以和Python原生数据类型相比,它显得较为笨重。但这并不是Numpy Array的本质问题,因为如果我们能够正确地使用它,我们就可以更好地掌控它的速度和内存使用。

Numpy Array操作速度

元素级操作

对于元素级操作,例如对于Numpy Array进行基本算术操作,使用Numpy Array时确实比直接使用Python列表更加高效。例如:

import time

arraySize = 10000000
x = range(arraySize)
y = range(arraySize)

arr1 = np.array(x)
arr2 = np.array(y)

start = time.time()
result = arr1 + arr2
print('Numpy addition time:', time.time() - start)

lst1 = list(x)
lst2 = list(y)

start = time.time()
result = [lst1[i] + lst2[i] for i in range(arraySize)]
print("List addition time: ", time.time() - start)
Python

得到如下结果:

Numpy addition time0.028188228607177734
Python list addition time1.4440968036651611
Python

从结果中可以看出,对于元素级操作,Numpy Array确实比Python列表更高效。

数组级操作

当涉及到数组级操作时,例如切片或重命名等,Numpy Array的运行速度相对较慢。这是因为这些操作需要在较大的内存块中进行操作,而Python固有的列表结构比Numpy较为适合这些操作。

让我们看一个例子,从一个Numpy Array中提取出所有偶数元素:

import time

arraySize = 10000000

arr = np.arange(arraySize)
start = time.time()

even_nums = [num for num in arr if num % 2 == 0]
print("Python list time: ", time.time() - start)

start = time.time()
even_nums = arr[arr % 2 == 0]
print("Numpy array time: ", time.time() - start)
Python

运行结果:

Python list time: 1.0547027587890625
Numpy array time: 0.27724695205688477
Python

运行结果显示,从Numpy Array中提取元素的速度会快得多。

内存使用问题

Numpy Array中的数据必须是相同类型的,这可以导致数据类型的转换更加麻烦,并且在这种情况下,内存使用可能称为一个问题。例如,如果我们在将Numpy Array从一种数据类型转换为另一种数据类型时,如果数据类型的大小不同,那么我们可能会浪费大量的内存。

例如:

import numpy as np
import time

arraySize = 10000000

arr = np.arange(arraySize, dtype='int16')
start = time.time()

new_arr = arr.astype('int32')

print("Execution time: ", time.time() - start)
Python

运行结果:

Execution time: 0.06471371650695801
Python

我们可以看到,即使只是将数据类型从int16转换为int32,内存使用也得增加一倍以上。

优化Numpy Array的性能

为了优化Numpy Array的性能,我们可以采取以下措施:

选择正确的数据类型

选择正确的数据类型可以最大限度地减少内存使用,从而优化我们的Numpy Array的性能。

对Numpy Array进行向量化操作

向量化操作可以使Numpy Array的速度更快。向量化的操作是指通过Numpy Array内部的内存块,而不是通过Python循环来处理数据。

例如:

import numpy as np
import time

arraySize = 10000000

arr = np.arange(arraySize, dtype='int16')
start = time.time()

new_arr = np.square(arr)

print("Execution time: ", time.time() - start)
Python

运行结果:

Execution time: 0.008820533752441406
Python

避免频繁的数据复制

频繁的数据复制可以导致Numpy Array的性能下降。如果我们需要创建一个独立的Numpy Array,我们应该使用.copy()方法,而不是简单地对原始Numpy Array进行分片或更改,从而避免对原始数据的复制。

总结

Numpy Array是一个强大的数据结构,但我们必须熟悉它的内存架构和数据类型等方面。在正确使用时,它可以减少内存使用和提高代码执行速度。

要优化Numpy Array的性能,我们需要选择正确的数据类型,避免频繁的数据复制,对Numpy Array进行向量化操作,同时也应该尽可能地避免元素级操作。通过上述方法,我们可以最大限度地优化Numpy Array的性能,使其更加高效。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册