Код C ++ для проверки гипотезы Коллатца быстрее, чем рукописная сборка - почему?

Правильным способом на данный момент является использование решения, рекомендованного @Roman Kuzmin в комментариях до @M. Dudley answer :

[IO.File]::WriteAllLines($filename, $content)

(я также немного сократил его, сняв ненужное пояснение пространства имен System - по умолчанию оно будет заменено автоматически).

790
задан einpoklum 4 August 2018 в 22:41
поделиться

2 ответа

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

Однако я считаю, что ваша методология профилирования имеет определенные недостатки. Ниже приведены общие рекомендации по профилированию:

  1. Убедитесь, что ваша система находится в нормальном / бездействующем состоянии. Остановите все запущенные процессы (приложения), которые вы запустили или которые интенсивно используют ЦП (или опросите по сети).
  2. Размер данных должен быть больше.
  3. Ваш тест должен длиться более 5-10 секунд.
  4. Не полагайтесь только на один образец. Выполните свой тест N раз. Соберите результаты и рассчитайте среднее значение или медиану результата.
5
ответ дан 4444 4 August 2018 в 22:41
поделиться

Даже не смотря на сборку, наиболее очевидная причина заключается в том, что /= 2, вероятно, оптимизирован как >>=1, и многие процессоры работают очень быстро. Но даже если процессор не имеет операции сдвига, целочисленное деление быстрее, чем деление с плавающей запятой.

Редактировать: Ваш пробег может варьироваться в зависимости от выражения «целочисленное деление быстрее, чем деление с плавающей запятой» выше. Комментарии ниже показывают, что современные процессоры отдают предпочтение оптимизации деления fp над целочисленным делением. Так что, если кто-то ищет наиболее вероятную причину ускорения, о которой спрашивает этот поток, то компилятор, оптимизирующий /=2 как >>=1, будет лучшим 1-м местом для поиска.


На не связанной ноте , если n нечетно, выражение n*3+1 всегда будет четным. Так что проверять не нужно. Вы можете изменить эту ветвь на

{
   n = (n*3+1) >> 1;
   count += 2;
}

Таким образом, весь оператор будет тогда

if (n & 1)
{
    n = (n*3 + 1) >> 1;
    count += 2;
}
else
{
    n >>= 1;
    ++count;
}
4
ответ дан Dmitry Rubanovich 4 August 2018 в 22:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: