Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

itertoolsで多重ループを回避してみる

More than 1 year has passed since last update.

なにをしたいのか

多重forループは実行速度を低下させる原因になるので、itertoolsでこれを回避し、速度の比較をしてみる。
(おまけ:numpyのbroadcastを全力で使ってfor文に対抗する)

方法

  • 2重のforループ、3重のforループ、4重のforループのそれぞれと、itertools.productで1重にした場合とを比較する。
  • 0から99の数字を総当たりで掛け合わせて、これらの合計を計算する。
  • 一応resultとして検算しておきます。

結果

うわっ…私の実行速度、遅すぎ…?
itertoolsの方が処理が遅いんですがなんででしょうか。

--- double_for ---
result 24502500
time : 0.000659942626953125
--- double_product ---
result 24502500
time : 0.0007491111755371094

--- triple_for ---
result 121287375000
time : 0.08507108688354492
--- triple_product ---
result 121287375000
time : 0.10134720802307129

--- quadruple_for ---
result 600372506250000
time : 11.622879981994629
--- quadruple_product ---
result 600372506250000
time : 13.198912858963013

実行したスクリプト

nested_loop.py
from itertools import product
import time


base_list = list(range(100))


def double_for():
    result = 0
    for i in base_list:
        for j in base_list:
            result += i * j
    print("result", result)


def double_product():
    result = 0
    pools = product(base_list, base_list)
    for i, j in pools:
        result += i * j
    print("result", result)


def triple_for():
    result = 0
    for i in base_list:
        for j in base_list:
            for k in base_list:
                result += i * j * k
    print("result", result)


def triple_product():
    result = 0
    pools = product(base_list, base_list, base_list)
    for i, j, k in pools:
        result += i * j * k
    print("result", result)


def quadruple_for():
    result = 0
    for i in base_list:
        for j in base_list:
            for k in base_list:
                for l in base_list:
                    result += i * j * k * l
    print("result", result)


def quadruple_product():
    result = 0
    pools = product(base_list, base_list, base_list, base_list)
    for i, j, k, l in pools:
        result += i * j * k * l
    print("result", result)


if __name__ == '__main__':
    print("-" * 3, "double_for", "-" * 3)
    t = time.time()
    double_for()
    print("time : ", time.time() - t)

    print("-" * 3, "double_product", "-" * 3)
    t = time.time()
    double_product()
    print("time : ", time.time() - t)

    print("-" * 3, "triple_for", "-" * 3)
    t = time.time()
    triple_for()
    print("time : ", time.time() - t)

    print("-" * 3, "triple_product", "-" * 3)
    t = time.time()
    triple_product()
    print("time : ", time.time() - t)

    print("-" * 3, "quadruple_for", "-" * 3)
    t = time.time()
    quadruple_for()
    print("time : ", time.time() - t)

    print("-" * 3, "quadruple_product", "-" * 3)
    t = time.time()
    quadruple_product()
    print("time : ", time.time() - t)

おまけ(これってnumpyで処理したほうが早いじゃん)

圧倒的ですね。

--- double_for ---
result 24502500
time : 0.0006780624389648438
--- double_numpy ---
result 24502500
time : 0.00026702880859375

--- triple_for ---
result 121287375000
time : 0.09470272064208984
--- triple_numpy ---
result 121287375000
time : 0.005362987518310547

--- quadruple_for ---
result 600372506250000
time : 12.442141771316528
--- quadruple_numpy ---
result 600372506250000
time : 0.5840020179748535

nested_loop_np.py
import numpy as np
import time


base_list = list(range(100))


def double_for():
    result = 0
    for i in base_list:
        for j in base_list:
            result += i * j
    print("result", result)


def double_np():
    a = np.arange(100).reshape(1, 1, 100)
    b = a.T
    result = np.sum(a * b)
    print("result", result)


def triple_for():
    result = 0
    for i in base_list:
        for j in base_list:
            for k in base_list:
                result += i * j * k
    print("result", result)


def triple_np():
    a = np.arange(100).reshape(1, 1, 100)
    b = a.reshape(1, 100, 1)
    c = a.reshape(100, 1, 1)
    result = np.sum(a * b * c)
    print("result", result)


def quadruple_for():
    result = 0
    for i in base_list:
        for j in base_list:
            for k in base_list:
                for l in base_list:
                    result += i * j * k * l
    print("result", result)


def quadruple_np():
    a = np.arange(100).reshape(1, 1, 1, 100)
    b = a.reshape(1, 1, 100, 1)
    c = a.reshape(1, 100, 1, 1)
    d = a.reshape(100, 1, 1, 1)
    result = np.sum(a * b * c * d)
    print("result", result)


if __name__ == '__main__':
    print("-" * 3, "double_for", "-" * 3)
    t = time.time()
    double_for()
    print("time : ", time.time() - t)

    print("-" * 3, "double_numpy", "-" * 3)
    t = time.time()
    double_np()
    print("time : ", time.time() - t)

    print("-" * 3, "triple_for", "-" * 3)
    t = time.time()
    triple_for()
    print("time : ", time.time() - t)

    print("-" * 3, "triple_numpy", "-" * 3)
    t = time.time()
    triple_np()
    print("time : ", time.time() - t)

    print("-" * 3, "quadruple_for", "-" * 3)
    t = time.time()
    quadruple_for()
    print("time : ", time.time() - t)

    print("-" * 3, "quadruple_numpy", "-" * 3)
    t = time.time()
    quadruple_np()
    print("time : ", time.time() - t)

tand826
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away