【问题标题】:Optimising this function优化此功能
【发布时间】:2012-03-05 13:22:02
【问题描述】:

我有一个脚本调用这个函数超过 100k 次,所以无论如何我都在寻找更多的性能。

您能否建议在 PHP 中计算标准偏差的优化方法或替代方法?

function calcStandardDev($samples){


    $sample_count = count($samples);

    for ($current_sample = 0; $sample_count > $current_sample; ++$current_sample) $sample_square[$current_sample] = pow($samples[$current_sample], 2);

    return sqrt(array_sum($sample_square) / $sample_count - pow((array_sum($samples) / $sample_count), 2));

}

【问题讨论】:

  • 您计算array_sum($sample_square) / $sample_count 两次。
  • @OliCharlesworth 第二次是array_sum($samples) / $sample_count。所以那里没有重复。
  • 也许this one 更快?

标签: php optimization micro-optimization


【解决方案1】:
$samples[$current_sample] * $samples[$current_sample]

会比

pow($samples[$current_sample], 2)

因为它没有函数调用的开销。

那么你也可以简化

pow((array_sum($samples) / $sample_count), 2));

防止再次调用 pow() 函数

为避免 array_sum($samples) 因该更改而被调用两次,请计算一次并在循环前存储到 var,然后只需在公式中引用该 var。

编辑

function calcStandardDev($samples){
    $sample_count = count($samples);
    $sumSamples = array_sum($samples);

    for ($current_sample = 0; $sample_count > $current_sample; ++$current_sample)
        $sample_square[$current_sample] = $samples[$current_sample] * $samples[$current_sample];


    return sqrt(array_sum($sample_square) / $sample_count - ( ($sumSamples / $sample_count) *
                                                              ($sumSamples / $sample_count)
                                                            )
               );

}

【讨论】:

  • 我不认为$samples 在每个循环调用中都相同
  • @Vytautas - 我看不到 $samples 在 OPs 问题中的任何变化
【解决方案2】:

foreach by reference 比 for 快,如果你已经有一个循环,你可以在这个循环中计算“sum”。并且 $x*$x 比 pow($x,2); 快得多 有一些功能比较。希望有所帮助。

你的函数微时间 = ~ 0.526

第二个函数 = ~ 0.290

  <?php
    function calcStandardDev($samples)
    {


        $sample_count = count($samples);

        for ($current_sample = 0; $sample_count > $current_sample; ++$current_sample) 
            $sample_square[$current_sample] = pow($samples[$current_sample], 2);

        return sqrt(array_sum($sample_square) / $sample_count - pow((array_sum($samples) / $sample_count), 2));

    }

    function calcStandardDev2($samples)
    {
        $sample_count = count($samples);

        $sum_sample_square  = 0;
        $sum_sample         = 0;

        foreach ($samples as &$sample) 
        {
            $sum_sample         += $sample;
            $sum_sample_square  += $sample * $sample; 
        }

        return sqrt($sum_sample_square / $sample_count - pow($sum_sample / $sample_count,2));

    }

     function calcStandardDev3($samples)
    {
        $sample_count = count($samples);

        $sum_sample_square  = 0;
        $sum_sample         = 0;

        foreach ($samples as &$sample) 
        {
            $sum_sample         += $sample;
            $sum_sample_square  += pow($sample ,2); 
        }

        return sqrt($sum_sample_square / $sample_count - pow($sum_sample  / $sample_count,2));

    }

    echo "<pre>";
    $samples = range(2,100000);

    $start  = microtime(true);
    echo calcStandardDev($samples)."\r\n";
    $end  = microtime(true);
    echo $end - $start ."\r\n";  
    echo "-------\r\n";

    $start  = microtime(true);
    echo calcStandardDev2($samples)."\r\n";
    $end  = microtime(true);
    echo $end - $start."\r\n";
    echo "-------\r\n";

    $start  = microtime(true);
    echo calcStandardDev3($samples)."\r\n";
    $end  = microtime(true);
    echo $end - $start;
    echo "-------\r\n";
?>

【讨论】:

  • 谢谢!在所有解决方案中 - 发布为 calcStandardDev2() 的解决方案是最快的
  • 我们已经计算出版本 2 是最快的,但是在返回中,你仍然有一个 pow(),这会不会更快地替换返回行中对 pow 的调用?我的测试说不,但差异很小 - 想法?
【解决方案3】:

通过自己计算各自的值来替换对array_sum 的调用。这样,您只需遍历数组一次而不是三次。

function calcStandardDev($samples){

    $sample_count = count($samples);
    $sum = 0;
    $sum_sqaure = 0;

    for ($current_sample = 0; $sample_count > $current_sample; ++$current_sample) {
        $sum_square += pow($samples[$current_sample], 2);
        $sum += $samples[$current_sample];
    }

    return sqrt( $sum_square / $sample_count - pow( $sum / $sample_count, 2));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多