Сколько стоит сэкономить, чтобы проверить перед вызовом sqrt при нормализации трехмерного вектора - PullRequest
0 голосов
/ 22 февраля 2019

AFAIK Операция sqrt стоит дорого в большинстве ситуаций.Приведенный ниже тест для вектора уже имеет длину 1 с эпсилоном?Это много экономит.Если normalize вызывается часто на векторах, которые уже нормализованы.Если не слишком дорого?

double Vec3d::normalize() {
    double  mod = x * x + y * y + z * z;
    if (mod == 0) {
        return(0);
    }
    if (consideredEqual(mod, 1.0, .0000001)) {  // is this test worth it ???
        return(1.0);
    }
    mod = std::sqrt(mod);
    x /= mod;
    y /= mod;
    z /= mod;
    return mod;
}

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

В современных микроархитектурах Pentium sqrt имеет задержку 10-22 цикла (для сравнения с 3cy для fp add, 5cy для fp mult и 2-4cy для преобразования типов fp-int),Стоимость значительно выше, особенно если учесть, что sqrt не является конвейером и запускать новую операцию можно только каждые 5 циклов.

Но добавление теста может быть не очень хорошей идеей, так как тест также имеетстоимость, которая должна быть учтена.В современных процессорах с глубоким конвейером инструкции выбираются заранее, чтобы заполнить конвейер, и ветке может потребоваться забыть все эти извлеченные инструкции.Чтобы ограничить этот неприятный эффект, процессоры пытаются «предсказать» поведение тестов: взяты ветки или нет и каков целевой адрес?Прогноз основан на регулярности поведения программы.Существующие предикторы очень хороши, и для многих проблем ветвь не имеет значительных затрат при правильном прогнозировании.Но предсказания могут не сработать, и неверный прогноз обойдется в 15-20 циклов, что очень высоко.

Теперь попробуйте примерно оценить, какой будет польза от предлагаемой вами модификации.Мы можем рассмотреть несколько сценариев.

  1. 90% значения времени равно! = 1,0, а в 10% случаев оно равно 1,0.Исходя из этого, предикторы ветвления будут держать пари, что вы не берете ветвь (значение! = 1,0).
    Таким образом, в 90% случаев у вас есть обычный sqrt для вычисления (а стоимость теста незначительна) и 10%.времени у вас есть неправильный прогноз.Вы избегаете 10-20 циклов sqrt, но вы платите штраф за 15 циклов.Коэффициент усиления равен нулю.

  2. 90% значения времени = 1,0, а в 10% случаев оно отличается.Предсказатели ветвлений предполагают, что вы берете ветвь.
    Когда значение равно 1,0, вы получаете явный выигрыш, а стоимость почти равна нулю.В 10% случаев вы заплатите за неверный прогноз филиала и кв.По сравнению со 100% кв. В среднем выигрыш.

  3. 50% значений равны 1,0, а 50% отличаются.Это как-то сценарий катастрофы.Предсказатели ветвления будут испытывать большие трудности в нахождении четкого поведения ветки и могут потерпеть неудачу значительную долю времени, скажем, от 40% до 100%, если вам очень не повезло.Вы добавите много ошибочных прогнозов ветвей к своим вычислительным затратам, и у вас может быть отрицательный выигрыш !!!

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

Вы можете найти показатели стоимости операций на сайте Agner Fog.https://www.agner.org/optimize

0 голосов
/ 22 февраля 2019

Хорошие ответы на вопрос ниже указывают на то, что это НЕ стоит для общего использования со стандартными библиотеками C и компиляторами и текущими процессорами с fpus.Но это может быть незначительным в известных ограниченных ситуациях или на процессорах без поддержки float.

c ++ практическая вычислительная сложность SQRT ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...