Оптимизация этой функции - PullRequest
0 голосов
/ 05 марта 2012

У меня есть скрипт, который вызывает эту функцию более 100 тыс. Раз, поэтому я в любом случае хочу выжать из него немного больше производительности.

Можете ли вы предложить оптимизацию или альтернативный метод для расчета стандартного отклонения?в 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));

}

Ответы [ 3 ]

1 голос
/ 05 марта 2012
$samples[$current_sample] * $samples[$current_sample]

будет быстрее, чем

pow($samples[$current_sample], 2)

, потому что у него нет накладных расходов на вызов функции.

Тогда вы также можете упростить

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

для предотвращения повторного вызова функции pow ()

Чтобы избежать повторного вызова array_sum ($ samples) в результате этого изменения, вычислите его один раз и сохраните в переменную перед циклом, а затем простоссылка на эту переменную в формуле.

РЕДАКТИРОВАТЬ

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)
                                                            )
               );

}
0 голосов
/ 05 марта 2012

foreach по ссылке быстрее, чем для, если у вас уже есть цикл, вы можете вычислить «сумму» в этом цикле. и $ x * $ x быстрее, чем pow ($ x, 2); Есть несколько функций сравнения. надеюсь помочь.

Ваша функция microtime = ~ 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";
?>
0 голосов
/ 05 марта 2012

Замените оба вызова на 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));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...