2013-03-07 2 views
0

Я пытаюсь улучшить свои навыки программирования для задания, которое будет выпущено в ближайшее время, оно предполагает решение проблемы, заставляя ее работать как можно эффективнее и быстрее. Я знаю, что это довольно сдержанная/небольшая часть кода, но как бы все могло ускорить ее работу.C++ - как улучшить скорость выполнения этих методов

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

double Analyser::averageVolume() 
{ 
    // Your code 
    double averageNumShares = 0; 
    for(int i = 0; i < nTransactions; i++) 
    { 
     averageNumShares += tArray[i].numShares; 
    } 
    averageNumShares = averageNumShares/nTransactions; 
    return averageNumShares; 
    //return 0 
} 
+0

Ну, вы могли бы вычислить сумму параллельно (используя многопоточность) ... –

+0

Что такое tArray? C++-массив или указатель на парные? – QuentinUK

+0

Это указатель, я должен был включить это, извините – user2075995

ответ

4

Если вам необходимо вычислить среднее значение из п чисел, я боюсь, что вы не можете ускорить его много мимо линейного времени Approch в примере кода ..

Если это не используется как часть другого более сложного алгоритма, в котором вы могли бы уйти, не имея необходимости вычислять среднее или что-то в этом направлении, принимая среднее значение будет O (n) которая в основном включает суммирование всех элементов массива и одного деления на количество элементов. Это именно то, что у вас есть.

+0

Спасибо :) Я ценю обратную связь, успокаивает мой разум – user2075995

+0

@Miky - Вы можете достичь O (1) - См. Ниже. –

0

Если вы используете уровень оптимизации gcc gcc.

+0

Я мог бы изучить это, может быть слишком продвинутым для меня, хотя lol – user2075995

+2

ключи командной строки слишком продвинуты? :( – KevinDTimm

+0

Действительно, вы должны иметь возможность изменить уровень оптимизации с любым компилятором. @ User2075995, добавление '-O2' в вашу командную строку компиляции слишком продвинуто? 8v) –

0

Короткий ответ: Этот код так же хорош, как и скорость. Что вы можете настроить, так это то, как вы его скомпилируете. Или, очевидно, перепишите его в сборке, если это вариант.

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

for(int i = 0; i < nTransactions; i++) 
    { 
     averageNumShares += tArray[i].numShares; 
    } 

в

pointerValue = &(tArray[0].numShares); 
pointerIncrement = sizeof(tArray[0]); 
for(int i = 0; i < nTransactions; i++) 
    { 
     averageNumShares += *(pointerValue++pointerIncrement); 
    } 

это может быть, что вы получите лучшую производительность, показывая компилятор все вы делаете прыжок ов er фиксированное смещение на каждой итерации цикла. Хороший компилятор должен иметь возможность увидеть это с помощью вашего исходного кода. И новый код может ухудшить производительность. Это действительно зависит от специфики вашего компилятора, и опять же, я не рекомендую этот подход, если вы не отчаянно нуждаетесь в лучшей производительности, чем то, что может предложить компилятор, и не хотите переходить на использование встроенной сборки или встроенных функций (если любой доступный).

+0

Спасибо, я ценю все отзывы об этом – user2075995

1

Почему бы не указать еще два значения для объекта - общее количество и количество элементов?

Тогда вычисление среднего может использовать эти числа. Быстро и просто (может быть встроенной функцией!).

+0

спасибо, я посмотрю, смогу ли я это реализовать! – user2075995

+0

BTW - сложность для среднего будет O (1) - намного лучше, чем O (N) –

+1

@ EdHeal - это просто сдвиг суммы. Это O (1), только если вызывается повторно для одного и того же массива. В противном случае это все равно O (n). Это ваше решение в основном для кэширования суммирования. Вы также можете кэшировать результат деления. Правильно?! –

0
int i= nTransactions; 
while(i--){// test for 0 is faster 
    averageNumShares += (q++)->numShares;// increment pointer is faster than offset 
} 
1

Вот один дополнительный подход, аналогичный предложенному Ed Heal, которые должны быть менее чувствительны к ошибкам округления. Ошибка округления среднего возрастает с размером накопленной суммы. Это может быть или не быть проблемой для вас, но это то, о чем нужно знать.

Вот итеративный алгоритм, который сводит к минимуму ошибки округления в среднем, что я первый наткнулся в старой редакции (около 1998) из Ross:

double Analyser::averageVolume() 
{ 
    double averageNumShares = 0.0; 

    for (int i = 0; i < nTransactions; i++) 
    { 
    double delta = (tArray[i].numShares - averageNumShares)/(i+1); 
    averageNumShares += delta; 
    } 

    return averageNumShares; 
} 

Это работает путем получения рекурсивного определения среднего , То есть, учитывая образцы x[1] ..., x[j], ..., x[N], вы можете вычислить среднее значение из первых M+1 образцов из образца x[M+1] и среднее из первых M образцов:

sum(M) = x[1] + x[2] + ... + x[M] 
thus avg(M+1) = sum(M+1)/(M+1) and avg(M) = sum(M)/M 

avg(M+1) - avg(M) = sum(M+1)/(M+1) - sum(M)/M 
    = [ M*sum(M+1) - (M+1)*sum(M) ]/[ M * (M+1) ] 
    = [ M*(x[M+1] + sum(M)) - M*sum(M) - sum(M) ]/[ M*(M+1) ] 
    = [ M*x[M+1] - sum(M) ]/[ M*(M+1) ] 
    = [ x[M+1] - avg(M) ]/(M+1) 
thus: avg(M+1) = avg(M) + [ x[M+1] - avg(M) ]/(M+1) 

Чтобы получить смысл ошибки округления для двух подходов, попробуйте вычислить среднее значение 10 7 выборок, каждый образец равен 1035,41. Ваш оригинальный подход возвращается (на моем оборудовании), в среднем 1035.40999988683. Итеративный подход выше возвращает точное среднее значение 1035,41.

Оба, к сожалению, являются O (N) в какой-то момент. В исходной схеме есть N дополнений и одно подразделение. Итеративная схема имеет N дополнений, вычитаний и делений, поэтому вы платите немного больше за точность.