Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.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代码比PHP中的相同代码慢100倍?_Php_Python_Performance_Cython_Python Multiprocessing - Fatal编程技术网

为什么我的Python代码比PHP中的相同代码慢100倍?

为什么我的Python代码比PHP中的相同代码慢100倍?,php,python,performance,cython,python-multiprocessing,Php,Python,Performance,Cython,Python Multiprocessing,我有两个点(x1和x2),希望在给定的步长计数中生成正态分布。x1和x2之间的x值的y值之和为1。针对实际问题: 我对Python相当陌生,不知道为什么下面的代码会产生期望的结果,但比PHP中的相同程序慢100倍。大约有2000个x1-x2对,每对大约有5个阶跃值 我尝试使用Cython进行编译,它使用了多处理,但它只是将事情改进了2倍,这仍然比PHP慢50倍。有没有建议如何提高速度以至少匹配PHP性能 from scipy.stats import norm import numpy as n

我有两个点(x1和x2),希望在给定的步长计数中生成正态分布。x1和x2之间的x值的y值之和为1。针对实际问题:

我对Python相当陌生,不知道为什么下面的代码会产生期望的结果,但比PHP中的相同程序慢100倍。大约有2000个x1-x2对,每对大约有5个阶跃值

我尝试使用Cython进行编译,它使用了多处理,但它只是将事情改进了2倍,这仍然比PHP慢50倍。有没有建议如何提高速度以至少匹配PHP性能

from scipy.stats import norm
import numpy as np
import time

# Calculates normal distribution
def calculate_dist(x1, x2, steps, slope):
    points = []
    range = np.linspace(x1, x2, steps+2)

    for x in range:
        y = norm.pdf(x, x1+((x2-x1)/2), slope)
        points.append([x, y])

    sum = np.array(points).sum(axis=0)[1]

    norm_points = []
    for point in points:
        norm_points.append([point[0], point[1]/sum])

    return norm_points

start = time.time()
for i in range(0, 2000):
    for j in range(10, 15):
        calculate_dist(0, 1, j, 0.15)

print(time.time() - start) # Around 15 seconds or so
编辑,PHP代码:

$start = microtime(true);

for ($i = 0; $i<2000; $i++) {
    for ($j = 10; $j<15; $j++) {
        $x1 = 0; $x2 = 1; $steps = $j; $slope = 0.15;
        $step = abs($x2-$x1) / ($steps + 1);

        $points = [];
        for ($x = $x1; $x <= $x2 + 0.000001; $x += $step) {
            $y = stats_dens_normal($x, $x1 + (($x2 - $x1) / 2), $slope);
            $points[] = [$x, $y];
        }

        $sum = 0;
        foreach ($points as $point) {
            $sum += $point[1];
        }

        $norm_points = [];
        foreach ($points as &$point) {
            array_push($norm_points, [$point[0], $point[1] / $sum]);
        }
    }
}

return microtime(true) - $start; # Around 0.1 seconds or so

答案是,您没有为python中的任务使用正确的工具/数据结构

在python中调用numpy函数有相当大的开销(
scipy.stats.norm.pdf
在引擎盖下使用numpy),因此人们永远不会为一个元素调用此函数,而是为整个数组调用(所谓的矢量化计算),这意味着

for x in range:
        y = norm.pdf(x, x1+((x2-x1)/2), slope)
        ys.append(y)
人们宁愿使用:

ys = norm.pdf(x,x1+((x2-x1)/2), slope)
计算x中所有元素的pdf并只支付一次开销,而不是
len(x)

例如,计算10^4个元素的pdf所需时间比计算一个元素所需时间少10倍:

%timeit norm.pdf(0)   # 68.4 µs ± 1.62 µs
%timeit norm.pdf(np.zeros(10**4))   # 415 µs ± 12.4 µs
使用矢量化计算不仅会使您的程序更快,而且通常会更短/更容易理解,例如:

def calculate_dist_vec(x1, x2, steps, slope):
    x = np.linspace(x1, x2, steps+2)
    y = norm.pdf(x, x1+((x2-x1)/2), slope)
    ys = y/np.sum(y)
    return x,ys
使用此矢量化版本可使速度提高10左右

问题是:
norm.pdf
针对长向量进行了优化(如果100万个元素的速度非常快,那么没有人真正关心10个元素的速度有多快/慢),但是您的测试对numpy有偏见,因为它只使用/创建短数组,因此
norm.pdf
无法发光


因此,如果它真的是关于小数组的,并且你真的想加速它,那么你就必须推出你自己的
norm.pdf
版本,使用cython创建这个快速而专门的函数可能值得一试。

我很好奇你是如何在PHP中运行相同的程序的。你需要添加与你的问题相当的PHP得到任何有意义的答案。抱歉,nowAhh补充道,完全有道理!!我的x向量相对较小,我们将看到何时/是否使用向量化计算的折衷是有意义的。谢谢你的回答!
def calculate_dist_vec(x1, x2, steps, slope):
    x = np.linspace(x1, x2, steps+2)
    y = norm.pdf(x, x1+((x2-x1)/2), slope)
    ys = y/np.sum(y)
    return x,ys