Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我不知道';我不明白这些方法中的一种为什么/如何比其他方法快_Python_Optimization_Numpy - Fatal编程技术网

Python 我不知道';我不明白这些方法中的一种为什么/如何比其他方法快

Python 我不知道';我不明白这些方法中的一种为什么/如何比其他方法快,python,optimization,numpy,Python,Optimization,Numpy,我想测试一些简单代码的实现之间的时间差异。我决定统计10000000个随机样本中有多少个值大于0.5。从[0.0,1.0]范围内均匀采集随机样本 这是我的密码: from numpy.random import random_sample; import time; n = 10000000; t1 = time.clock(); t = 0; z = random_sample(n); for x in z: if x > 0.5: t += 1; print t; t2

我想测试一些简单代码的实现之间的时间差异。我决定统计10000000个随机样本中有多少个值大于0.5。从[0.0,1.0]范围内均匀采集随机样本

这是我的密码:

from numpy.random import random_sample; import time; 
n = 10000000;

t1 = time.clock();

t = 0;
z = random_sample(n);
for x in z:
    if x > 0.5: t += 1;
print t;

t2 = time.clock();

t = 0;
for _ in xrange(n):
    if random_sample() > 0.5: t += 1;
print t;

t3 = time.clock();

t = (random_sample(n) > 0.5).sum();
print t;

t4 = time.clock();

print t2-t1; print t3-t2; print t4-t3;
这是输出:

4999445
4999511
5001498
7.0348236652
1.75569394301
0.202538106332

我知道第一个实现很糟糕,因为创建一个庞大的数组,然后按元素计算是个坏主意,所以我认为第二个实现将是最有效的

但是第三种方法的实现速度是第二种方法的10倍吗?第三种方法不也是以
random\u sample(n)
的形式创建一个庞大的数组,然后根据0.5检查值吗

第三种方法与第一种方法有何不同?为什么比第一种方法快35倍


编辑:@merlin2011建议方法3可能不会在内存中创建完整的数组。因此,为了测试该理论,我尝试了以下方法:

z = random_sample(n);
t = (z > 0.5).sum();
print t;
0.197948451549
的时间内运行,这实际上与方法3相同。因此,这可能不是一个因素

  • 方法1在使用前会在内存中生成一个完整的列表。这很慢,因为必须先分配内存,然后再访问,可能会多次丢失缓存

  • 方法2使用生成器,它从不在内存中创建列表,而是根据需要生成每个元素

  • 方法3可能更快,因为
    sum()
    C
    中被实现为一个循环,但我不是100%确定。我猜这会更快,原因与Matlab矢量化比Matlab中的
    循环快一样

  • 更新:将三个步骤分开,我观察到方法3仍然同样快,因此我必须同意utdemir的观点,即每个操作员执行的指令更接近机器代码

    z = random_sample(n)
    z2 = z > 0.5
    t = z2.sum();
    
    在前两种方法中,您都调用Python的标准功能来执行循环,这比烘焙到实现中的C级循环慢得多

  • 方法1在使用前会在内存中生成一个完整的列表。这很慢,因为必须先分配内存,然后再访问,可能会多次丢失缓存

  • 方法2使用生成器,它从不在内存中创建列表,而是根据需要生成每个元素

  • 方法3可能更快,因为
    sum()
    C
    中被实现为一个循环,但我不是100%确定。我猜这会更快,原因与Matlab矢量化比Matlab中的
    循环快一样

  • 更新:将三个步骤分开,我观察到方法3仍然同样快,因此我必须同意utdemir的观点,即每个操作员执行的指令更接近机器代码

    z = random_sample(n)
    z2 = z > 0.5
    t = z2.sum();
    
    在前两种方法中,您都调用Python的标准功能来执行循环,这比烘焙到实现中的C级循环慢得多

  • 方法1在使用前会在内存中生成一个完整的列表。这很慢,因为必须先分配内存,然后再访问,可能会多次丢失缓存

  • 方法2使用生成器,它从不在内存中创建列表,而是根据需要生成每个元素

  • 方法3可能更快,因为
    sum()
    C
    中被实现为一个循环,但我不是100%确定。我猜这会更快,原因与Matlab矢量化比Matlab中的
    循环快一样

  • 更新:将三个步骤分开,我观察到方法3仍然同样快,因此我必须同意utdemir的观点,即每个操作员执行的指令更接近机器代码

    z = random_sample(n)
    z2 = z > 0.5
    t = z2.sum();
    
    在前两种方法中,您都调用Python的标准功能来执行循环,这比烘焙到实现中的C级循环慢得多

  • 方法1在使用前会在内存中生成一个完整的列表。这很慢,因为必须先分配内存,然后再访问,可能会多次丢失缓存

  • 方法2使用生成器,它从不在内存中创建列表,而是根据需要生成每个元素

  • 方法3可能更快,因为
    sum()
    C
    中被实现为一个循环,但我不是100%确定。我猜这会更快,原因与Matlab矢量化比Matlab中的
    循环快一样

  • 更新:将三个步骤分开,我观察到方法3仍然同样快,因此我必须同意utdemir的观点,即每个操作员执行的指令更接近机器代码

    z = random_sample(n)
    z2 = z > 0.5
    t = z2.sum();
    
    在前两种方法中,您都调用Python的标准功能来执行循环,这比烘焙到实现中的C级循环慢得多。

    AFAIK

    • 函数调用很重,在方法2上,调用
      random\u sample()
      10000000次,但在第三个方法上,只调用一次
    • Numpy的
      .sum
      在C语言中优化到最后一位,也很可能使用SIMD指令来避免循环
    所以

    在方法2中,您使用Python进行比较和循环;但在方法3中,您更接近处理器,使用优化的指令进行比较和求和。

    AFAIK

    • 函数调用很重,在方法2上,调用
      random\u sample()
      10000000次,但在第三个方法上,只调用一次
    • Numpy的
      .sum
      在C语言中被优化到最后一位,也是最重要的