通过数组或使用函数存储值? (优化)

时间:2015-09-12 19:37:55

标签: python arrays matlab function optimization

在Python中,我有一个变量x(取决于另一个可变i),它采用以下值:

x = 0.5 for i=11 or i=111 
x = 1   for 12<=i<=100 or 112<=i<=200
x = 0   for the rest of the values of i (i takes integer values from 1 to 300)

我希望在循环内多次使用x的值(其中i不是迭代器)。存储x:数组或函数?

的值的更好(计算时间节省)方法

我可以将它存储为长度为300的数组并指定上面的值。或者我可以使用get_x作为输入值i,并根据if条件给出上述值。

我想优化代码的时间。哪种方式会更好? (我也试图在Python和MATLAB中实现它。)

3 个答案:

答案 0 :(得分:3)

答案完全取决于您的应用,无论如何,我倾向于避免过早优化的理念。可能只是以任何看起来最干净或对你最有意义的方式实现它,如果它最终太慢,尝试不同的东西。

但如果你真的坚持看到真实的结果,那就让我们来看看吧。这是我用来运行它的代码:

import time
import random

def get_x(i):
    if i == 11 or i == 111:
        return 0.5
    if (12 <= i and i <= 100) or (112 <= i and i <= 200):
        return 1
    return 0

x_array = [get_x(i) for i in range(300)]
i_array = [i % 300 for i in range(1000000)]
print "Sequential access"
start = time.time()
for i in i_array:
    x = get_x(i)
end = time.time()
print "get_x method:", end-start

start = time.time()
for i in i_array:
    x = x_array[i]
end = time.time()
print "Array method:", end-start
print

random.seed(123)
i_array = [random.randint(0,299) for i in range(1000000)]
print "Random access"
start = time.time()
for i in i_array:
    x = get_x(i)
end = time.time()
print "get_x method:", end-start

start = time.time()
for i in i_array:
    x = x_array[i]
end = time.time()
print "Array method:", end-start

以下是打印出来的内容:

Sequential access
get_x method: 0.264999866486
Array method: 0.108999967575

Random access
get_x method: 0.263000011444
Array method: 0.108999967575

总的来说,这两种方法都不是很慢,这适用于10 ^ 6次访问,并且它们都可以在四分之一秒内轻松完成。 get_x方法看起来似乎是数组方法的两倍慢。但是,这不会是循环逻辑的缓慢部分!你在循环中放入的任何其他内容肯定是程序执行时间的主要原因。您绝对应该选择使代码更容易维护的方法,这可能是get_x方法。

答案 1 :(得分:1)

我更喜欢这个函数,也许它可能会慢一些,因为函数在内存堆栈中创建了一个新的作用域,但它更具可读性,正如Python的Zen所说:“简单比复杂更好。”

答案 2 :(得分:1)

预先计算x,然后对每次查找执行查找会更快,但只有在每次运行程序时进行足够的查找以超过预计算所有值的成本时才会收回成本。盈亏平衡点可以基于基准计算,但也许不值得努力。另一种策略是不进行预计算,但是每次计算都会记忆或缓存其结果。一些缓存策略(如reddis和memcache)允许程序运行之间存在持久性。

基于timeit测试,列表访问速度比计算快3.5-7.3倍,具体取决于i的值。以下是一些测试结果。

def f(i):
    if i == 11 or i == 111:
        return .5
    else:
        if i >= 12 and i <= 100 or i >= 112 and i <= 200:
            return 1
    return 0

timeit f(11)
10000000 loops, best of 3: 139 ns per loop

timeit f(24)
1000000 loops, best of 3: 215 ns per loop

timeit f(150)
1000000 loops, best of 3: 249 ns per loop

timeit f(105)
1000000 loops, best of 3: 267 ns per loop

timeit f(237)
1000000 loops, best of 3: 289 ns per loop

x = range(300)

timeit x[150]
10000000 loops, best of 3: 39.5 ns per loop

timeit x[1]
10000000 loops, best of 3: 39.7 ns per loop

timeit x[299]
10000000 loops, best of 3: 39.7 ns per loop