Выполнение векторного присвоения после функции

#c #performance #directx #xna-math-library

#c #Производительность #directx #xna-математическая библиотека

Вопрос:

Я использую этот код:

 MainLoop() {
    for (int i = 0; i < length; i  ) {
        XMVector3Rotate(rays[i], orientation);
    }
}
  

и у меня есть fps 1900000, но когда я использую этот:

 MainLoop() {
    for (int i = 0; i < length; i  ) {
        calculatedRays[i] = XMVector3Rotate(rays[i], orientation);
    }
}
  

У меня fps = 200.
Почему?

Комментарии:

1. Если вы говорите, что FPS = 1900000 (а не 190.0000), это невозможно с текущим оборудованием, у вас ошибка в вычислении FPS (время кадра = 0.0000001 сек).

2. Я пишу программный рендерер, и это FPS с использованием описанного цикла в основном цикле рендеринга. Это означает, что за одну секунду выполняется 1900000 кадров с циклическими вычислениями.

3. ОК… тогда вы, должно быть, почти ничего не делаете (мы говорим о времени кадра в субмикросекунду). И так, как это связано с XNA?

4. Я отредактировал ваши теги и заголовок. Это функция DirectX, а не функция XNA.

5.Ах … Я вижу, откуда берется тег XNA. XMVector3Rotate из математической библиотеки очень запутанным названием. Который является частью DirectX. Не XNA. (Отличная идея, Microsoft.)

Ответ №1:

Когда вы делаете это:

 XMVector3Rotate(rays[i], orientation);
  

Я предполагаю, что компилятор вводит функцию — и видит это, поскольку ее результат нигде не присваивается — на самом деле он ничего не делает и полностью удаляет вызов функции. Это очень быстро, потому что на самом деле ничего не делает.

Но затем, когда вы добавляете в присваивание:

 calculatedRays[i] = XMVector3Rotate(rays[i], orientation);
  

Внезапно вы выполняете кучу операций чтения и записи в память и различные математические операции — все из которых были пропущены ранее.

(Вы пометили этот XNA-файл — но это функция C . Большинство компиляторов C могут и будут встраивать функции, подобные этой. Стандартный компилятор C # не может.)

Комментарии:

1. 1 опередил меня — компилятор оптимизирует строку в первом сценарии. И, поскольку это единственное содержимое в цикле for, компилятор, вероятно, удаляет и это…

2. Если компилятор избегает этой строки, почему fps такой маленький? Потому что, когда я использую свой собственный код без asm, simd, FPS = 400

3. Если тестовая программа OP так же проста, как и то, что он опубликовал, я полагаю, компилятор оптимизировал весь цикл, а не только тело цикла.

4. @itun В первом случае (без присвоения) — компилятор ничего не выводит для этой строки. Во втором случае — компилятор что -то выдает. Если у вас есть своя альтернатива для XMVector3Rotate , которая в два раза быстрее — тогда молодец! Если вы уверены, что это правильно, тогда не стесняйтесь использовать его вместо этого. (Преимущество использования библиотеки Microsoft: они протестировали это на практике).

Ответ №2:

В первом примере результат функции сразу отбрасывается (не присваивается). Компилятор достаточно умен, чтобы почувствовать это, и опускает вызов метода…

Ответ №3:

Предполагая, что XMVector3Rotate возвращает тип XNA Vector3, это будет операция копирования структуры, относительно дорогостоящая по производительности.

При оптимизации моей собственной игры XNA для XBox360 я заменил многие подобные операции на ref тип параметров, с очень заметным выигрышем в тяжелых циклах.

РЕДАКТИРОВАТЬ: пример (из памяти)

 Vector3 vec1 = something, vec2 = something, resu<
Vector3.Add(ref vec1, ref vec2, out result);