来自c的美丽世界,我正在尝试理解这种行为:
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
...:
不甚至在分钟之后完成,我知道列表sizes
不是那么大,长度不到205k。但是,这立即执行 :
In [8]: min_item = min(sizes)
In [9]: for item in sizes:
if(item == min_item):
count = count + 1
...:
那发生了什么?
我的猜测:python无法理解min(sizes)
将始终是常量,因此在前几次调用之后用其返回值替换..因为Python使用解释器.. 子>
min()的参考并没有说任何可以向我解释此事的内容,但我想的是它可能需要查看分区来做到这一点,但那不应该&情况确实如此,因为sizes
是 list
,而不是 RDD
!
编辑:
这是我困惑的根源,我在C中写了一个类似的程序:
for(i = 0; i < SIZE; ++i)
if(i == mymin(array, SIZE))
++count;
并得到了这些时间:
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.
对于时间安排,我使用了Time measurements中的Nomimal Animal's方法。
答案 0 :(得分:5)
我绝不是蟒蛇内部运作方面的专家,但从我的理解到目前为止你想比较的速度
for item in sizes:
if(item == min(sizes)):
count = count + 1
和
min_item = min(sizes)
for item in sizes:
if(item == min_item):
count = count + 1
如果我有任何错误,现在有人纠正我,
在python列表中是可变的并且没有固定的长度,并且被视为这样,而在C中,数组具有固定的大小。来自this question:
Python列表非常灵活,可以保存完全异构的任意数据,并且可以在摊销的常量时间内非常有效地附加。如果你需要时间有效地缩小和扩展阵列而不需要麻烦,那么它们就是你要走的路。但是他们比C阵列使用更多的空间。
现在举个例子
for item in sizes:
if(item == min(sizes)):
new_item = item - 1
sizes.append(new_item)
然后item == min(sizes)
的值在下一次迭代时会有所不同。 Python不会缓存min(sizes)
的结果值,因为它会破坏上面的示例,或者需要一些逻辑来检查列表是否已更改。相反,它留给你。通过定义min_item = min(sizes)
,您实际上是在自己缓存结果。
既然数组在C中是一个固定的大小,它可以找到min值而不是python列表的开销,因此我认为它在C中没有问题(以及C)是一种低级语言。)
同样,我不完全理解python的底层代码和编译,并且我确定如果你在python中分析循环的过程,你会看到python反复计算{{ 1}},导致极端延迟。我希望更多地了解python的内部工作原理(例如,是否有任何方法在python的循环中缓存,或者每次迭代都会再次计算所有内容?)所以如果有人有更多的信息和/或更正,让我知道!