<p>问题是你的假设,你测量除法或乘法所需的时间,这是不正确的。您正在测量除法或乘法所需的开销。在</p>
<p>我们真的要看确切的代码来解释每种效果,因为版本不同而不同。这个答案只能给出一个想法,一个必须考虑的问题。在</p>
<p>问题是一个简单的<code>int</code>在python中一点都不简单:它是一个真正的对象,必须在垃圾收集器中注册,它的大小随着它的值而增长-对于所有你必须付出的代价:例如,对于一个8位整数,需要24字节的内存!python浮动也是如此。在</p>
<p>另一方面,一个numpy数组由简单的c风格的整数/浮点数组成,没有开销,您可以节省大量内存,但在访问numpy数组的一个元素时需要为此付出代价。<code>a[i]</code>意味着:必须构造一个python整数,并将其注册到垃圾回收器中,并且只有在它可以使用时才可以使用它,这会产生大量的开销。在</p>
<p>考虑以下代码:</p>
<pre><code>li1=[x%256 for x in xrange(10**4)]
arr1=np.array(li1, np.uint8)
def arrmult(a):
for i in xrange(len(a)):
a[i]*=5;
</code></pre>
<p><code>arrmult(li1)</code>比<code>arrmult(arr1)</code>快25,因为列表中的整数已经是python int,不必创建!大部分的计算时间是用来创建对象的——其他的几乎可以忽略不计。在</p>
<hr/>
<p>让我们看看你的代码,首先是乘法:</p>
^{pr2}$
<p>对于uint8,必须发生以下情况(为了简单起见,我忽略了+5):</p>
<ol>
<li>必须创建python int</li>
<li>必须将其强制转换为float(python float creation),以便能够进行浮点乘法</li>
<li>并转换回python int或/和uint8</li>
</ol>
<p>对于float32,要做的工作更少(乘法不需要太多):
1创建了一个python float
2铸造后浮动32。在</p>
<p>应该是更快的版本。在</p>
<hr/>
<p>现在让我们来看看这个部门:</p>
<pre><code>def arrdiv2(a):
...
b[i, j] = (b[i, j] + 5) / 2
</code></pre>
<p>这里的陷阱是:所有操作都是整数运算。因此,与乘法相比,不需要强制转换为python float,因此与乘法相比,我们的开销更小。对于unint8,除法比乘法快。在</p>
<p>然而,对于float32,除法和乘法同样快/慢,因为在这种情况下几乎没有什么变化-我们仍然需要创建一个python float。在</p>
<hr/>
<p>现在的矢量化版本:它们可以使用c风格的“原始”float32s/uint8而无需转换(及其成本!)到引擎盖下相应的python对象。为了得到有意义的结果,你应该增加迭代的次数(现在运行时间太少,不能肯定地说些什么)。在</p>
<ol>
<li><p>float32的除法和乘法可以有相同的运行时间,因为我希望numpy通过<code>0.5</code>的乘法来替换除法2(但是为了确保人们必须查看代码)。</p></li>
<li><p>uint8的乘法应该慢一些,因为每个uint8整数在与0.5相乘之前必须强制转换为浮点,然后再转换回uint8。</p></li>
<li><p>对于uint8的情况,numpy不能用0.5代替2的除法,因为它是整数除法。对于许多架构,整数除法比浮点乘法慢-这是最慢的矢量化操作。</p></li>
</ol>
<hr/>
<p>附言:我不想过多地讨论成本乘法和除法,还有太多的其他事情会对性能产生更大的影响。例如,创建不必要的临时对象,或者如果numpy数组很大并且不能放入缓存中,那么内存访问将成为瓶颈—您将看不到乘法和除法之间的任何区别。在</p>