2012-02-17 23 views
11

Tôi đang cố sử dụng mô-đun itertools của Python để tăng tốc độ lồng nhau ba vòng lặp. Các mã kiểm tra dưới đây so sánh một vòng lặp lồng nhau ba tiêu chuẩn với itertools' phương pháp sản phẩm và đầu ra:Python itertools - chậm?

Nested thời gian loop = 2,35023 giây

Itertools thời gian loop = 2,67766 giây

Tôi có thiếu cái gì?

import numpy 
import itertools 
import time 

n = 128 
a = numpy.arange(n**3).reshape((n,n,n)) 
b = numpy.zeros((n,n,n)) 
c = numpy.zeros((n,n,n)) 

t = time.time() 
for i in range(n): 
    for j in range(n): 
     for k in range(n): 
      b[i,j,k] = a[i,j,k] 
print 'Nested loop time = %g secs' % (time.time() - t) 

t = time.time() 
for (i,j,k) in itertools.product(range(n), repeat=3): 
    c[i,j,k] = a[i,j,k] 
print 'Itertools loop time = %g secs' % (time.time() - t) 
+0

"Tôi có thiếu gì đó không?" - Những gì bạn dường như bị thiếu là không ai tuyên bố rằng ý tưởng của 'itertools.product()' là tăng tốc độ lồng nhau cho vòng lặp - –

+3

@Sven Marnach 9.7. itertools - Các hàm tạo các trình vòng lặp cho vòng lặp hiệu quả ... http: //docs.python.org/library/itertools.html –

Trả lời

9

Nó có vẻ như itertools.product là chậm hơn cho các giá trị lớn n:

 
In [24]: print _23 
from itertools import product 

def nested_loops(n): 
    for i in range(n): 
     for j in range(n): 
      for k in range(n): 
       pass 

def itertools_product(n): 
    for (i,j,k) in product(range(n), repeat=3): 
     pass 


In [25]: %timeit nested_loops(128) 
10 loops, best of 3: 68.6 ms per loop 

In [26]: %timeit itertools_product(128) 
10 loops, best of 3: 162 ms per loop 

In [27]: %timeit nested_loops(10) 
10000 loops, best of 3: 84.5 us per loop 

In [28]: %timeit itertools_product(10) 
10000 loops, best of 3: 79.8 us per loop 

In [30]: %timeit nested_loops(300) 
1 loops, best of 3: 833 ms per loop 

In [31]: %timeit itertools_product(300) 
1 loops, best of 3: 2.07 s per loop 

Và nếu không có sự giải nén tuple:

 
In [40]: print _39 
from itertools import product 

def itertools_product(n): 
    for ijk in product(range(n), repeat=3): 
     pass 

In [41]: %timeit itertools_product(128) 
10 loops, best of 3: 115 ms per loop 

In [42]: %timeit itertools_product(10) 
10000 loops, best of 3: 59.2 us per loop 

In [43]: %timeit itertools_product(300) 
1 loops, best of 3: 1.47 s per loop 

Ngoài ra, để cho vui, comprehensions danh sách và các biểu thức máy phát điện :

 
def list_comprehension_product(n): 
    range_n = range(n) 
    for (i,j,k) in [ (i, j, k) for i in range_n for j in range_n for k in range_n ]: 
     pass 

def generator_expression_product(n): 
    range_n = range(n) 
    for (i,j,k) in ((i, j, k) for i in range_n for j in range_n for k in range_n): 
     pass 

In [51]: %timeit list_comprehension_product(128) 
1 loops, best of 3: 583 ms per loop 

In [52]: %timeit generator_expression_product(128) 
1 loops, best of 3: 480 ms per loop 

Những tiêu chuẩn được chạy với python --version:

2.6.7 (r267:88850, Jul 31 2011, 19:30:54) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]
+1

Có, nó có vẻ chậm hơn đối với các phạm vi rộng lớn. Và đó chính xác là nơi bạn muốn nó nhanh hơn - đúng không? – repoman

5

Nó dường như là vòng lặp thứ hai là chậm hơn so với lần đầu tiên, có lẽ vì sự giải nén tuple. Bạn không cần phải làm điều đó, và tôi thấy nó làm cho vòng lặp thứ hai nhanh hơn để làm điều đó như thế này:

for ijk in itertools.product(range(n), repeat=3): 
    c[ijk] = a[ijk] 

Tất nhiên, với NumPy, bạn muốn tránh lặp qua các yếu tố ở tất cả, và thay vào đó sử dụng hoạt động gumpy trên toàn bộ mảng cùng một lúc. Bằng cách đó, tất cả các vòng lặp, vv, đang được thực hiện trong C, và bạn sẽ nhận được tăng tốc rất lớn.

+0

Không muốn điều này có liên quan đến gumpy. Chỉ cần sử dụng numpy để có một cái gì đó mà sẽ cho phép lập chỉ mục ba nhanh chóng. Có thể là một cuộc gọi đến một số chức năng với một đối số ba ... – repoman

Các vấn đề liên quan