วิธีที่มีประสิทธิภาพมากที่สุดในการทำแผนที่ฟังก์ชั่นผ่านอาร์เรย์ที่มีจำนวนมาก


338

เป็นวิธีที่มีประสิทธิภาพที่สุดในการแมปฟังก์ชั่นมากกว่าอาร์เรย์ numpy คืออะไร? วิธีที่ฉันทำในโครงการปัจจุบันของฉันมีดังนี้:

import numpy as np 

x = np.array([1, 2, 3, 4, 5])

# Obtain array of square of each element in x
squarer = lambda t: t ** 2
squares = np.array([squarer(xi) for xi in x])

อย่างไรก็ตามดูเหมือนว่ามันอาจจะไม่มีประสิทธิภาพมากนักเนื่องจากฉันใช้ list comprehension เพื่อสร้าง array ใหม่เป็นรายการ Python ก่อนที่จะแปลงกลับไปเป็น array numpy

เราทำได้ดีกว่านี้ไหม


10
ทำไมไม่ "squares = x ** 2" คุณมีฟังก์ชั่นที่ซับซ้อนมากกว่าที่คุณต้องการประเมินหรือไม่?
22

4
เกี่ยวกับเท่านั้นsquarer(x)?
ชีวิต

1
บางทีนี่อาจไม่ใช่การตอบคำถามโดยตรง แต่ฉันได้ยินมาว่าnumbaสามารถรวบรวมรหัสไพ ธ อนที่มีอยู่ในคำแนะนำเครื่องแบบขนานได้ ฉันจะกลับมายังและแก้ไขโพสต์นี้เมื่อฉันมีโอกาสใช้จริง
把友情留在无盐

x = np.array([1, 2, 3, 4, 5]); x**2ทำงาน
Shark Deng

คำตอบ:


282

ฉันได้ทดสอบวิธีการที่แนะนำทั้งหมดพร้อมnp.array(map(f, x))กับperfplot(โครงการเล็ก ๆ ของฉัน)

ข้อความ # 1: หากคุณสามารถใช้ฟังก์ชันดั้งเดิมของ numpy ให้ทำเช่นนั้น

หากฟังก์ชั่นที่คุณกำลังพยายามที่จะ vectorize แล้วจะ vectorized (เหมือนx**2เช่นในโพสต์ต้นฉบับ) โดยใช้ที่มีมากได้เร็วขึ้นกว่าสิ่งอื่น (โปรดทราบขนาดล็อก):

ป้อนคำอธิบายรูปภาพที่นี่

ถ้าคุณต้องการ vectorization จริง ๆ แล้วมันไม่สำคัญว่าคุณใช้ตัวแปรตัวไหน

ป้อนคำอธิบายรูปภาพที่นี่


รหัสในการทำซ้ำแปลง:

import numpy as np
import perfplot
import math


def f(x):
    # return math.sqrt(x)
    return np.sqrt(x)


vf = np.vectorize(f)


def array_for(x):
    return np.array([f(xi) for xi in x])


def array_map(x):
    return np.array(list(map(f, x)))


def fromiter(x):
    return np.fromiter((f(xi) for xi in x), x.dtype)


def vectorize(x):
    return np.vectorize(f)(x)


def vectorize_without_init(x):
    return vf(x)


perfplot.show(
    setup=lambda n: np.random.rand(n),
    n_range=[2 ** k for k in range(20)],
    kernels=[f, array_for, array_map, fromiter, vectorize, vectorize_without_init],
    xlabel="len(x)",
)

7
ดูเหมือนว่าคุณจะf(x)ออกจากพล็อตของคุณ อาจใช้ไม่ได้กับทุกคนfแต่ใช้ได้ที่นี่และเป็นวิธีแก้ปัญหาที่เร็วที่สุดเมื่อใช้งานได้ง่าย
user2357112 รองรับโมนิก้า

2
นอกจากนี้พล็อตของคุณไม่สนับสนุนการเรียกร้องของคุณที่vf = np.vectorize(f); y = vf(x)ชนะสำหรับอินพุตสั้น ๆ
user2357112 รองรับโมนิก้า

หลังจากติดตั้ง perfplot (v0.3.2) ผ่าน pip ( pip install -U perfplot) ฉันเห็นข้อความ: AttributeError: 'module' object has no attribute 'save'เมื่อวางโค้ดตัวอย่าง
tsherwen

สิ่งที่เกี่ยวกับวานิลลาสำหรับวง?
Catiger3331

1
@Vlad เพียงใช้ math.sqrt ตามความเห็น
Nico Schlömer

138

numpy.vectorizeวิธีการเกี่ยวกับการใช้

import numpy as np
x = np.array([1, 2, 3, 4, 5])
squarer = lambda t: t ** 2
vfunc = np.vectorize(squarer)
vfunc(x)
# Output : array([ 1,  4,  9, 16, 25])

36
มันไม่มีประสิทธิภาพมากกว่านี้อีกแล้ว
user2357112 รองรับ Monica

78
จากเอกสารนั้น: The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop. ในคำถามอื่น ๆ ฉันพบว่าvectorizeอาจเพิ่มความเร็วการทำซ้ำของผู้ใช้เป็นสองเท่า แต่การเร่งความเร็วที่แท้จริงคือnumpyการทำงานของอาเรย์จริง
hpaulj

2
โปรดทราบว่าอย่างน้อย vectorize จะทำให้สิ่งต่าง ๆ ทำงานได้ดีกับอาร์เรย์ที่ไม่ใช่แบบ 1d
Eric

แต่squarer(x)จะใช้ได้กับอาร์เรย์ที่ไม่ใช่แบบ 1d อยู่แล้ว vectorizeเท่านั้นจริงๆมีความได้เปรียบเหนือความเข้าใจรายการ (เช่นในคำถาม) squarer(x)ไม่เกิน
user2357112 รองรับโมนิก้า

79

TL; DR

ตามที่บันทึกไว้โดย@ user2357112วิธี "โดยตรง" ของการใช้ฟังก์ชั่นจะเป็นวิธีที่เร็วและง่ายที่สุดในการแมปฟังก์ชั่นผ่านอาร์เรย์ Numpy เสมอ:

import numpy as np
x = np.array([1, 2, 3, 4, 5])
f = lambda x: x ** 2
squares = f(x)

โดยทั่วไปจะหลีกเลี่ยงnp.vectorizeเนื่องจากมันทำงานได้ไม่ดีและมี (หรือมี) ปัญหาจำนวนหนึ่ง หากคุณกำลังจัดการประเภทข้อมูลอื่น ๆ คุณอาจต้องการตรวจสอบวิธีการอื่นที่แสดงด้านล่าง

การเปรียบเทียบวิธีการ

นี่คือการทดสอบอย่างง่ายเพื่อเปรียบเทียบสามวิธีในการจับคู่ฟังก์ชันตัวอย่างนี้ใช้กับ Python 3.6 และ NumPy 1.15.4 ก่อนอื่นฟังก์ชั่นการตั้งค่าสำหรับการทดสอบ:

import timeit
import numpy as np

f = lambda x: x ** 2
vf = np.vectorize(f)

def test_array(x, n):
    t = timeit.timeit(
        'np.array([f(xi) for xi in x])',
        'from __main__ import np, x, f', number=n)
    print('array: {0:.3f}'.format(t))

def test_fromiter(x, n):
    t = timeit.timeit(
        'np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))',
        'from __main__ import np, x, f', number=n)
    print('fromiter: {0:.3f}'.format(t))

def test_direct(x, n):
    t = timeit.timeit(
        'f(x)',
        'from __main__ import x, f', number=n)
    print('direct: {0:.3f}'.format(t))

def test_vectorized(x, n):
    t = timeit.timeit(
        'vf(x)',
        'from __main__ import x, vf', number=n)
    print('vectorized: {0:.3f}'.format(t))

การทดสอบกับห้าองค์ประกอบ (เรียงลำดับจากเร็วไปช้า):

x = np.array([1, 2, 3, 4, 5])
n = 100000
test_direct(x, n)      # 0.265
test_fromiter(x, n)    # 0.479
test_array(x, n)       # 0.865
test_vectorized(x, n)  # 2.906

ด้วยองค์ประกอบ 100s:

x = np.arange(100)
n = 10000
test_direct(x, n)      # 0.030
test_array(x, n)       # 0.501
test_vectorized(x, n)  # 0.670
test_fromiter(x, n)    # 0.883

และด้วยองค์ประกอบอาร์เรย์ 1,000 รายการขึ้นไป:

x = np.arange(1000)
n = 1000
test_direct(x, n)      # 0.007
test_fromiter(x, n)    # 0.479
test_array(x, n)       # 0.516
test_vectorized(x, n)  # 0.945

Python / NumPy รุ่นต่าง ๆ และการปรับแต่งคอมไพเลอร์จะได้ผลลัพธ์ที่ต่างกันดังนั้นทำการทดสอบที่คล้ายกันสำหรับสภาพแวดล้อมของคุณ


2
หากคุณใช้countอาร์กิวเมนต์และนิพจน์ตัวสร้างนั้นnp.fromiterจะเร็วกว่าอย่างมาก
juanpa.arrivillaga

3
ตัวอย่างเช่นใช้'np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))'
juanpa.arrivillaga

4
คุณไม่ได้ทดสอบการแก้ปัญหาโดยตรงของf(x), ซึ่งเต้นทุกอย่างอื่นมากกว่าลำดับความสำคัญ
user2357112 รองรับโมนิก้า

4
ถ้าfมี 2 ​​ตัวแปรและอาร์เรย์เป็น 2D
Sigur

2
ฉันสับสนว่าเวอร์ชัน 'f (x)' ("โดยตรง") นั้นมีการพิจารณาเปรียบเทียบกันอย่างไรเมื่อ OP ถามวิธี "แมป" ฟังก์ชั่นข้ามอาร์เรย์ ในกรณีของ f (x) = x ** 2 ** จะถูกดำเนินการโดย numpy ในอาร์เรย์ทั้งหมดที่ไม่ได้อยู่ในองค์ประกอบพื้นฐาน ตัวอย่างเช่นถ้า f (x) คือ 'lambda x: x + x "คำตอบนั้นแตกต่างกันมากเพราะ numpy เชื่อมต่ออาร์เรย์แทนที่จะทำต่อองค์ประกอบนอกจากนี้นี่เป็นการเปรียบเทียบที่ตั้งใจจริงหรือไม่โปรดอธิบาย
Andrew Mellinger

49

มีnumexpr , numbaและcythonอยู่รอบ ๆ เป้าหมายของคำตอบนี้คือการคำนึงถึงความเป็นไปได้เหล่านี้

แต่ก่อนอื่นเราจะระบุให้ชัดเจน: ไม่ว่าคุณจะจับคู่ฟังก์ชั่นของ Python ลงบน numpy-array ได้อย่างไรมันยังคงเป็นฟังก์ชั่น Python ซึ่งหมายความว่าสำหรับการประเมินทุกครั้ง

  • องค์ประกอบ numpy-array ต้องถูกแปลงเป็น Python-object (เช่น a Float)
  • การคำนวณทั้งหมดเสร็จสิ้นด้วย Python-objects ซึ่งหมายความว่ามีค่าใช้จ่ายของ interpreter, การจัดส่งแบบไดนามิกและวัตถุที่ไม่เปลี่ยนรูป

ดังนั้นเครื่องจักรที่ใช้ในการวนซ้ำจริง ๆ อาร์เรย์ไม่ได้มีบทบาทใหญ่เพราะค่าใช้จ่ายดังกล่าวข้างต้น - มันยังคงช้ากว่าการใช้ฟังก์ชั่นในตัวของ numpy

ลองมาดูตัวอย่างต่อไปนี้:

# numpy-functionality
def f(x):
    return x+2*x*x+4*x*x*x

# python-function as ufunc
import numpy as np
vf=np.vectorize(f)
vf.__name__="vf"

np.vectorizeถูกเลือกเป็นตัวแทนของคลาสฟังก์ชันของ pure-python การใช้perfplot(ดูรหัสในภาคผนวกของคำตอบนี้) เราจะได้เวลาทำงานต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่

เราสามารถเห็นได้ว่าวิธีการของ numpy นั้นเร็วกว่ารุ่น python แท้ถึง 10x-100x การลดลงของประสิทธิภาพสำหรับขนาดอาร์เรย์ที่ใหญ่กว่าอาจเป็นเพราะข้อมูลไม่เหมาะกับแคชอีกต่อไป

มันเป็นสิ่งที่ควรค่าแก่การกล่าวถึงซึ่งvectorizeใช้หน่วยความจำจำนวนมากดังนั้นบ่อยครั้งที่การใช้หน่วยความจำคือคอขวด (ดูคำถามที่เกี่ยวข้องกับSO ) นอกจากนี้โปรดทราบว่าเอกสารของ numpy np.vectorizeระบุว่าเป็น "ให้ไว้เพื่อความสะดวกเป็นหลักไม่ใช่เพื่อประสิทธิภาพ"

ควรใช้เครื่องมืออื่นเมื่อต้องการประสิทธิภาพนอกเหนือจากการเขียน C-extension ตั้งแต่เริ่มต้นแล้วมีความเป็นไปได้ดังต่อไปนี้:


หนึ่งมักจะได้ยินว่าประสิทธิภาพของก้อนนั้นดีเท่าที่จะได้รับเพราะมันเป็นซีบริสุทธิ์ภายใต้ประทุน ยังมีห้องพักจำนวนมากสำหรับการปรับปรุง!

vectorized numpy-version ใช้หน่วยความจำเพิ่มเติมและการเข้าถึงหน่วยความจำจำนวนมาก Numexp-library พยายามเรียงไพ่ numpy-arrays และทำให้การใช้งานแคชดีขึ้น:

# less cache misses than numpy-functionality
import numexpr as ne
def ne_f(x):
    return ne.evaluate("x+2*x*x+4*x*x*x")

นำไปสู่การเปรียบเทียบต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันไม่สามารถอธิบายทุกอย่างในพล็อตด้านบน: เราสามารถเห็นค่าใช้จ่ายที่ใหญ่กว่าสำหรับ numexpr-library ในตอนเริ่มต้น แต่เนื่องจากมันใช้แคชได้ดีกว่าจึงเร็วกว่าประมาณ 10 เท่าสำหรับอาร์เรย์ที่ใหญ่กว่า!


อีกวิธีหนึ่งคือการคอมไพล์ฟังก์ชั่นของ jit และทำให้ได้ UF-pure แท้ นี่คือแนวทางของ numba:

# runtime generated C-function as ufunc
import numba as nb
@nb.vectorize(target="cpu")
def nb_vf(x):
    return x+2*x*x+4*x*x*x

มันเร็วกว่า numpy-approach 10 เท่า:

ป้อนคำอธิบายรูปภาพที่นี่


อย่างไรก็ตามงานนั้นขนานได้อย่างน่าอับอายดังนั้นเราสามารถใช้prangeเพื่อคำนวณลูปในแบบขนาน:

@nb.njit(parallel=True)
def nb_par_jitf(x):
    y=np.empty(x.shape)
    for i in nb.prange(len(x)):
        y[i]=x[i]+2*x[i]*x[i]+4*x[i]*x[i]*x[i]
    return y

ฟังก์ชั่นขนานจะช้ากว่าสำหรับอินพุตที่เล็กกว่า แต่เร็วกว่า (เกือบ 2 เท่า) สำหรับขนาดที่ใหญ่กว่า:

ป้อนคำอธิบายรูปภาพที่นี่


ในขณะที่ numba เชี่ยวชาญในการปรับการทำงานให้เหมาะสมกับ numpy-arrays แต่ Cython เป็นเครื่องมือทั่วไป มันมีความซับซ้อนมากขึ้นในการดึงประสิทธิภาพเช่นเดียวกับ numba - บ่อยครั้งที่มันจะลงไปที่ lvm (numba) กับคอมไพเลอร์ท้องถิ่น (gcc / MSVC):

%%cython -c=/openmp -a
import numpy as np
import cython

#single core:
@cython.boundscheck(False) 
@cython.wraparound(False) 
def cy_f(double[::1] x):
    y_out=np.empty(len(x))
    cdef Py_ssize_t i
    cdef double[::1] y=y_out
    for i in range(len(x)):
        y[i] = x[i]+2*x[i]*x[i]+4*x[i]*x[i]*x[i]
    return y_out

#parallel:
from cython.parallel import prange
@cython.boundscheck(False) 
@cython.wraparound(False)  
def cy_par_f(double[::1] x):
    y_out=np.empty(len(x))
    cdef double[::1] y=y_out
    cdef Py_ssize_t i
    cdef Py_ssize_t n = len(x)
    for i in prange(n, nogil=True):
        y[i] = x[i]+2*x[i]*x[i]+4*x[i]*x[i]*x[i]
    return y_out

Cython ส่งผลให้ฟังก์ชั่นค่อนข้างช้า:

ป้อนคำอธิบายรูปภาพที่นี่


ข้อสรุป

เห็นได้ชัดว่าการทดสอบเพียงหนึ่งฟังก์ชั่นไม่ได้พิสูจน์อะไรเลย สิ่งหนึ่งที่ควรระลึกไว้เช่นสำหรับฟังก์ชั่นที่เลือกไว้แบนด์วิดท์ของหน่วยความจำคือคอขวดสำหรับขนาดที่ใหญ่กว่า 10 ^ 5 องค์ประกอบ - ดังนั้นเราจึงมีประสิทธิภาพเหมือนกันสำหรับ numba, numexpr และ cython ในภูมิภาคนี้

ในที่สุดคำตอบสุดท้ายจะขึ้นอยู่กับประเภทของฟังก์ชั่นฮาร์ดแวร์การกระจายแบบ Python และปัจจัยอื่น ๆ ยกตัวอย่างเช่นงูกระจายใช้ของ Intel VML สำหรับฟังก์ชั่น numpy และจึงมีประสิทธิภาพเหนือกว่า numba (เว้นแต่จะใช้ SVML, เห็นนี้SO-โพสต์ ) ได้อย่างง่ายดายสำหรับฟังก์ชั่นยอดเยี่ยมชอบexp, sin, cosและที่คล้ายกัน - ดูเช่นต่อไปนี้SO-โพสต์

จากการตรวจสอบนี้และจากประสบการณ์ของฉันจนถึงตอนนี้ฉันจะบอกว่า numba ดูเหมือนจะเป็นเครื่องมือที่ง่ายที่สุดที่มีประสิทธิภาพดีที่สุดตราบใดที่ไม่มีฟังก์ชั่นยอดเยี่ยม


พล็อตเวลาทำงานด้วยperfplot - แพ็คเกจ :

import perfplot
perfplot.show(
    setup=lambda n: np.random.rand(n),
    n_range=[2**k for k in range(0,24)],
    kernels=[
        f, 
        vf,
        ne_f, 
        nb_vf, nb_par_jitf,
        cy_f, cy_par_f,
        ],
    logx=True,
    logy=True,
    xlabel='len(x)'
    )

1
Numba สามารถใช้ประโยชน์จาก Intel SVML ซึ่งส่งผลให้มีการกำหนดเวลาเปรียบเทียบได้ค่อนข้างมากเมื่อเทียบกับ Intel VML แต่การติดตั้งใช้งานเป็นบิตในรุ่น (0.43-0.47) ฉันได้เพิ่มพล็อตประสิทธิภาพการทำงานstackoverflow.com/a/56939240/4045774 สำหรับการเปรียบเทียบใน cy_expsum ของคุณ
max9111

29
squares = squarer(x)

การดำเนินการทางคณิตศาสตร์ในอาร์เรย์จะถูกนำไปใช้แบบอัตโนมัติตามลำดับโดยมีลูประดับ C ที่มีประสิทธิภาพซึ่งหลีกเลี่ยงค่าใช้จ่ายของล่ามทั้งหมดที่จะนำไปใช้กับลูประดับ Python หรือความเข้าใจ

ฟังก์ชั่นส่วนใหญ่ที่คุณต้องการนำไปใช้กับองค์ประกอบอาร์เรย์ NumPy จะทำงานได้แม้ว่าบางฟังก์ชันอาจต้องการการเปลี่ยนแปลง ตัวอย่างเช่นifใช้งานไม่ได้ตามองค์ประกอบ คุณต้องการที่จะแปลงไฟล์เหล่านั้นเพื่อใช้งานสร้างnumpy.where:

def using_if(x):
    if x < 5:
        return x
    else:
        return x**2

กลายเป็น

def using_where(x):
    return numpy.where(x < 5, x, x**2)

8

ฉันเชื่อในเวอร์ชั่นที่ใหม่กว่า (ฉันใช้ 1.13) ของ numpy คุณสามารถเรียกใช้ฟังก์ชั่นได้โดยการส่ง numpy array ไปยัง fuction ที่คุณเขียนสำหรับสเกลาร์ชนิดมันจะใช้การเรียกใช้ฟังก์ชั่นแต่ละองค์ประกอบผ่านอาร์เรย์ numpy อีกอาร์เรย์ numpy

>>> import numpy as np
>>> squarer = lambda t: t ** 2
>>> x = np.array([1, 2, 3, 4, 5])
>>> squarer(x)
array([ 1,  4,  9, 16, 25])

3
นี่ไม่ใช่เรื่องใหม่จากระยะไกล - เป็นเรื่องที่เกิดขึ้นเสมอ - เป็นหนึ่งในคุณสมบัติหลักของ numpy
Eric

8
มันเป็นผู้ประกอบการที่ใช้คำนวณในแต่ละองค์ประกอบตัน** tนั่นเป็นเรื่องธรรมดา การห่อในนั้นlambdaไม่ได้ทำอะไรพิเศษ
hpaulj

สิ่งนี้ไม่สามารถใช้งานได้หากคำสั่งที่แสดงอยู่ในปัจจุบัน
TriHard8

8

ในหลายกรณีnumpy.apply_along_axisจะเป็นตัวเลือกที่ดีที่สุด มันเพิ่มประสิทธิภาพโดยประมาณ 100 เท่าเมื่อเทียบกับวิธีการอื่น ๆ - และไม่เพียง แต่สำหรับฟังก์ชั่นการทดสอบเล็กน้อยเท่านั้น

เมื่อฉันเพิ่มวิธีการ:

def along_axis(x):
    return np.apply_along_axis(f, 0, x)

เพื่อโค้ด perfplot ฉันได้รับผลลัพธ์ต่อไปนี้: ป้อนคำอธิบายรูปภาพที่นี่


ฉันตกใจอย่างยิ่งกับความจริงที่ว่าคนส่วนใหญ่ไม่ได้ตระหนักถึงความเรียบง่ายที่ปรับขนาดได้และไม่มีในตัวเกมนี้มานานหลายปี ....
บิลหวาง

7

ดูเหมือนว่าไม่มีใครพูดถึงวิธีการผลิตในโรงงานufuncในแพคเกจ numpy: np.frompyfuncซึ่งฉันได้ทำการทดสอบอีกครั้งnp.vectorizeและมีประสิทธิภาพที่ดีกว่าประมาณ 20 ~ 30% แน่นอนว่ามันจะทำงานได้ดีตามรหัส C ที่กำหนดหรือแม้กระทั่งnumba(ซึ่งฉันไม่ได้ทดสอบ) แต่มันก็เป็นทางเลือกที่ดีกว่าnp.vectorize

f = lambda x, y: x * y
f_arr = np.frompyfunc(f, 2, 1)
vf = np.vectorize(f)
arr = np.linspace(0, 1, 10000)

%timeit f_arr(arr, arr) # 307ms
%timeit vf(arr, arr) # 450ms

ฉันได้ทดสอบตัวอย่างขนาดใหญ่ขึ้นและการปรับปรุงก็เป็นสัดส่วน ดูเอกสารประกอบได้ที่นี่


1
ฉันทำซ้ำการทดสอบเวลาข้างต้นและพบว่ามีการปรับปรุงประสิทธิภาพ (มากกว่า np.vectorize) ประมาณ 30%
Julian - BrainAnnex.org


2

คำตอบทั้งหมดข้างต้นเปรียบเทียบได้ดี แต่ถ้าคุณจำเป็นต้องใช้ฟังก์ชั่นที่กำหนดเองสำหรับการทำแผนที่และคุณมีnumpy.ndarrayและคุณจะต้องรักษารูปร่างของอาร์เรย์

ฉันได้เปรียบเทียบเพียงสอง ndarrayแต่มันจะรักษารูปร่างของ ฉันใช้อาร์เรย์ที่มี 1 ล้านรายการเพื่อเปรียบเทียบ ที่นี่ฉันใช้ฟังก์ชั่นสแควร์ซึ่งยัง inbuilt ใน numpy และมีการเพิ่มประสิทธิภาพที่ดีเนื่องจากมีสิ่งที่ต้องการคุณสามารถใช้ฟังก์ชั่นที่คุณเลือก

import numpy, time
def timeit():
    y = numpy.arange(1000000)
    now = time.time()
    numpy.array([x * x for x in y.reshape(-1)]).reshape(y.shape)        
    print(time.time() - now)
    now = time.time()
    numpy.fromiter((x * x for x in y.reshape(-1)), y.dtype).reshape(y.shape)
    print(time.time() - now)
    now = time.time()
    numpy.square(y)  
    print(time.time() - now)

เอาท์พุต

>>> timeit()
1.162431240081787    # list comprehension and then building numpy array
1.0775556564331055   # from numpy.fromiter
0.002948284149169922 # using inbuilt function

ที่นี่คุณสามารถเห็นnumpy.fromiterผลงานที่ดีโดยพิจารณาจากวิธีการที่ง่ายและหากมีฟังก์ชั่น inbuilt โปรดใช้สิ่งนั้น


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.