python足够聪明,可以用常量结果替换函数调用吗?

gsa*_*ras 6 c python optimization performance apache-spark

来自美丽的世界,我正在尝试理解这种行为:

In [1]: dataset = sqlContext.read.parquet('indir')
In [2]: sizes = dataset.mapPartitions(lambda x: [len(list(x))]).collect()
In [3]: for item in sizes:
   ...:     if(item == min(sizes)):
   ...:         count = count + 1
   ...:         
Run Code Online (Sandbox Code Playgroud)

甚至不会在20 分钟后完成,我知道名单sizes不是那么大,不到205k的长度.然而,这立即执行:

In [8]: min_item = min(sizes)

In [9]: for item in sizes:
    if(item == min_item):
        count = count + 1
   ...:         
Run Code Online (Sandbox Code Playgroud)

所以发生了什么事?

我的猜测:无法理解min(sizes)它将永远是常量,因此在前几次调用之后用它的返回值替换..因为Python使用解释器..


min()的参考没有说任何可以解释这个问题的东西,但我想的是它可能需要查看分区才能做到这一点,但事实并非如此,因为sizes是一个list,而不是一个RDD!


编辑:

这是我困惑的根源,我在C中写了一个类似的程序:

for(i = 0; i < SIZE; ++i)
    if(i == mymin(array, SIZE))
        ++count;
Run Code Online (Sandbox Code Playgroud)

得到了这些时间:

C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
That took 98.679177000 seconds wall clock time.
C02QT2UBFVH6-lm:~ gsamaras$ gcc -O3 -Wall main.c
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
That took 0.000000000 seconds wall clock time.
Run Code Online (Sandbox Code Playgroud)

为了时间安排,我在时间测量中使用了Nomimal Animal的方法.

Xan*_*ano 5

我不是python内部工作的专家,但从我的理解到目前为止你想要比较速度

for item in sizes:
    if(item == min(sizes)):
        count = count + 1
Run Code Online (Sandbox Code Playgroud)

min_item = min(sizes)
for item in sizes:
    if(item == min_item):
        count = count + 1
Run Code Online (Sandbox Code Playgroud)

如果我有任何这个错误,现在有人纠正我,但是,

在python列表中是可变的并且没有固定的长度,并且被视为这样,而在C中,数组具有固定的大小.从这个问题:

Python列表非常灵活,可以保存完全异构的任意数据,并且可以在摊销的常量时间内非常有效地附加.如果你需要时间有效地缩小和扩展阵列而不需要麻烦,那么它们就是你要走的路.但是他们比C阵列使用更多的空间.

现在举个例子

for item in sizes:
    if(item == min(sizes)):
        new_item = item - 1
        sizes.append(new_item)
Run Code Online (Sandbox Code Playgroud)

那么item == min(sizes)下一次迭代的值会有所不同.Python不会缓存结果值,min(sizes)因为它会破坏上面的示例,或者需要一些逻辑来检查列表是否已更改.相反,它留给你.通过定义min_item = min(sizes)您实际上是自己缓存结果.

既然数组在C中是一个固定的大小,它可以找到min值而不是python列表的开销,因此我认为它在C中没有问题(以及C是一个低级语言).

同样,我不完全理解python的底层代码和编译,我确定如果你分析python中循环的过程,你会看到python反复计算min(sizes),导致极端的延迟.我想更多地了解python的内部工作原理(例如,是否有任何方法缓存在python的循环中,或者每次迭代都会再次计算所有内容?)所以如果有人有更多的信息和/或更正,那么让我吧知道!