Эффективность циклов, написанных вручную, против перегрузок операторов - PullRequest
1 голос
/ 22 апреля 2010

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

В процессе написания моего кода у меня возникло желание просто свернуть свой собственный класс Vector с простыми арифметическими перегрузками (+, -, * /), чтобы я мог упростить такие выражения, как:

// old:
for (int i = 0; i < 3; i++)
    r[i] = r1[i] - r2[i];

// new:
r = r1 - r2;

Что должно быть более или менее идентично в генерируемом коде. Но когда дело доходит до более сложных вещей, может ли это сильно повлиять на мою производительность? Один пример из моего кода:

Версия, написанная вручную:

for (int j = 0; j < 3; j++)
{
    p.vel[j] = p.oldVel[j] + (p.oldAcc[j] + p.acc[j]) * dt2 + (p.oldJerk[j] - p.jerk[j]) * dt12;
    p.pos[j] = p.oldPos[j] + (p.oldVel[j] + p.vel[j]) * dt2 + (p.oldAcc[j] - p.acc[j]) * dt12;
}

Использование класса Vector с перегрузками операторов:

p.vel = p.oldVel + (p.oldAcc + p.acc) * dt2 + (p.oldJerk - p.jerk) * dt12;
p.pos = p.oldPos + (p.oldVel + p.vel) * dt2 + (p.oldAcc - p.acc) * dt12;

Я пытаюсь оптимизировать мой код для скорости, так как этот код выполняется внутри внутренних циклов. Повлияет ли использование перегруженных операторов на эти вещи на производительность? Я делаю некоторое численное интегрирование системы из n взаимно гравитирующих тел. Эти векторные операции чрезвычайно распространены, поэтому очень важно иметь быстрый запуск.

Буду признателен за любую проницательность, равно как и за любые идиомы или уловки, о которых я не знаю.

Ответы [ 3 ]

2 голосов
/ 22 апреля 2010

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

Помимо производительности, вы также упоминаете, что расчеты должны быть точными. Наличие в классе специфичных для вектора вычислений означает, что их проще тестировать по отдельности, а также что код, использующий класс, становится короче и проще в обслуживании.

2 голосов
/ 22 апреля 2010

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

Встраивание вручную также значительно увеличивает риск ошибок, потому что вы не будете повторно использовать ни одного хорошо проверенного кода, вы будете писать один и тот же код снова и снова. Я бы порекомендовал написать код с операторами, а затем , если , вы можете доказать, что можете ускорить его, вручную вставив, продублировав код и вручную вставив вторую версию. Затем вы можете запустить два варианта кода друг против друга, чтобы доказать (а), что ручное встраивание эффективно, и (б) что читаемый и вручную встроенный код дает одинаковый результат.

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

1 голос
/ 29 апреля 2010

Ознакомьтесь с примерами кода ConCRT

http://code.msdn.microsoft.com/concrtextras/Release/ProjectReleases.aspx?ReleaseId=4270

Есть пара (включая пример NBody), которые делают кучу трюков, подобных этим, с типами и шаблонами Vector и т. Д.

...