【发布时间】:2018-10-12 03:31:59
【问题描述】:
我有两个点(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
编辑 2,分析每一行,发现 norm.pdf() 占用了 98% 的时间,因此找到了一个自定义 normpdf 函数并对其进行了定义,现在时间约为 0.67 秒,这要快得多,但仍慢 10 倍左右比 PHP。另外我认为重新定义常用函数有悖于 Python 的简单性?!
自定义函数(来源是其他一些 Stackoverflow 答案):
from math import sqrt, pi, exp
def normpdf(x, mu, sigma):
u = (x-mu)/abs(sigma)
y = (1/(sqrt(2*pi)*abs(sigma)))*exp(-u*u/2)
return y
【问题讨论】:
-
我很好奇您是如何设法在 PHP 中运行 same 程序的。
-
您需要将 PHP 等效项添加到您的问题中才能获得任何有意义的答案。
-
抱歉,现在添加
标签: php python performance cython python-multiprocessing