Обновить
129
Артём@Zealint

Пользователь

27
Подписчики
Отправить сообщение
На всякий случай, вынужден пояснить один философский момент из нашей жизни. В нашей жизни многие вещи определяются косвенно, так как напрямую их определить нельзя вообще никак. Так, например, учёные не могут разглядеть и замерить свойства квантовых частиц, но определяют их физику по косвенным признакам, в результате соударения их друг об друга. Получаемая физиками модель отвечает на ряд вопросов, важных для физиков. Далее, в реальных условиях человек не бегает по беговой дорожке в соответствующей одежде, однако если взять двух людей на беговой дорожке и двух людей, бегущих за троллейбусом, то и там, и там оба покажут качественно одинаковый результат (тот прибежит первым, кто лучше к этому подготовлен). В мире всё так, эксперимент есть эксперимент, и если я говорю, что мне нужны эти данные и я знаю, что с ними делать, значит на то у меня есть основания, диктуемые опытом. А кому кажется, что тут нет ВООБЩЕ никакой связи — ну значит это его мнение, пусть кажется дальше. Любой факт может иметь значение для того, кто в теме. Кто не в теме, тому это может ничего не говорить. Вот на этом можно и остановить разговор.
Это ещё нужно доказать, что не имеют отношения. Подобные голословные заключения здесь мало полезны.
Попробую на пальцах объяснить.
Есть функция f, а есть функция g. Есть цикл, внутрь которого мы встраиваем эти функции. С функцией f получаем время A, с функцией g получаем время B. Есть ещё время C, когда цикл почти пустой (там только генерация данных). Я вычисляю (A-C) и (B-C), называя это практически чистым временем работы функции. Я называют это этим словом, то есть даю название этим значениям (Вы можете называть их «грязным временем», суть это не поменяет). Эти значения разные, они показывают то, насколько одна функция быстрее или медленнее другой (можно даже не вычитать C, если угодно, но я хочу вычитать).
Вы понимаете? Я получаю два разных числа и на основе их соотношения делаю приблизительный вывод о скорости работы функций. Этот вывод коррелирует с реальностью. Я не говорю, что данные числа отражают реальность, я говорю, что если в этом эксперименте одна функция сильно быстрее другой, то в реальности будет ТО ЖЕ САМОЕ. Это понятно? Если нет, то что именно не так?
Смысл есть всегда. В данном случае мы пытаемся отыскать разницу по времени работы функций по отношению друг к другу. Наши измерения показывают эту разницу и в ней есть смысл. Или Вы хотите утверждать, что если, скажем, в наших экспериментах одна функция быстрее другой в 10 раз, то в реальных программах со случайным потоком данных может статься наоборот?
В таком случае нет смысла мне сообщать, что я что-то делаю неправильно. Я же назвал условия эксперимента. Вы же спорите с тем, как Вы представляете себе этот эксперимент, а не я.
Да сколько можно… я не говорю нигде про отдельное измерение. Я сказал, что получаю почти чистое время работы функции в этих конкретных условиях. Это время не является точным, но оно коррелирует с реальностью. С тем, как функция будет вести себя в практических приложениях. Вы же, невнимательно прочитав мой ответ, считаете, что я делаю абсолютно точные вычисления и спорите с этой выдумкой. Не надо так.
Ещё Вы неверно поняли смысл пустого цикла (посмотрите всё-таки программу и мой комментарий выше внимательнее). Пустым я назвал цикл, в котором есть вычисление потока данных. То есть формула там тоже присутствует.
Мы сейчас разговариваем не о способе измерения времени, а о том, что по Вашим словам стоимость ветвления равна нулю. Это не так и это нетрудно показать. Тот факт, что я не вполне корректно измеряю время работы функции мне и так хорошо известен. Но других вариантов, увы, не вижу. Этот способ хотя бы как-то коррелирует со сложностью функции.
Я измеряю время работы пустого цикла, который генерирует входные данные, затем полного цикла, который вместе с генерацией данных вызывает функцию. В ассемблерном листинге я убедился, что генерация происходит в регистре. Затем я вычитаю время работы полного цикла и пустого — получаю почти чисто время работы функции. А мы наблюдаем, что разница между одной и другой версией колоссальна. Версия с ветвлением может работать в несколько десятков раз медленнее, чем без ветвлений при хаотичной подаче, когда как при последовательной подаче версия с ветвлением выигрывает. Это можно объяснить только тем, что ветвление играет роль в вычислениях, особенно когда предсказатель не может надёжно предсказывать.
Нет, дело не в этом. Когда данные подаются хаотично (по формуле), переменная также находится в регистре, я проверял (там же она пересчитывается). Более того, я всегда вычитаю время работы самого вычисления этих данных, оставляя чистое время работы самой функции.
На самом деле это неправда. Если бы стоимость была 0 тактов, то не было бы разницы между последовательным и хаотичным потоком данных.
Вот же незадача. Даже не знаю, что делать. Volatile мне не подходит, она тупит в некоторых компиляторах, подобные пустые циклы, оказалось, тоже не подходят. Я подумаю…
Видео, конечно, полезное для многих, спасибо за ссылку, но касательно моих интересов там нет ничего.

Вот представьте: мне нужна программа, которую любой пользователь может скомпилировать и запустить у себя, она выдаст время работы функций и всё. Не нужно, чтобы пользователь устанавливал бы себе дополнительные пакеты или делал какие-то дополнительные действия.

Далее, если говорить о честном тестировании функций, то тут вообще беда — даже хаотичное тестирование в цикле не сильно полезно (в малых циклах процессор может кэшировать сразу уже раскодированные команды при первом проходе, не раскодируя их затем при остальных), так как в реальных условиях, особенно когда нужная нам функция окружена некими другими командами, всё может быть совершенно иначе. Я ищу разные варианты решения этой проблемы, но пока не нахожу. Пока прихожу к выводу, что оптимизация программ в современных процессорах — это IT-аналог гадания на кофейной гуще. Хоть что делай — мы не знаем, что с этим сделает процессор, особенно если учесть, что ряд команд он преобразует во внутренние RISC команды которые (кстати) могут оказаться с ветвлениями (хотя исходные команды были без них). И вот об этих тонкостях работы микрокоманд хотелось бы узнавать из подобных видео. О том, насколько вообще честно мы можем измерить время работы функции, чтобы это было близко к реальным условиям.
Это мне известно, вот и интересно, насколько результат будет другим. Вообще по-хорошему для видеокарты нужно делать тесты иначе, запускать там 1 поток и делать по нему выводу — плохая идея. Нужна другая система тестирования, учитывающая её особенность.
Я вообще-то написал про cmovXX, и сообщил, что компилятор может использовать данную конструкцию при необходимости. Да, у хорошего компилятора не будет ветвлений, но я веду речь про тех программистов, кто до сих пор этого не знает. С другой стороны, как выяснилось, при хаотичном потоке данных функции без ветвлений (sign, abs) на x86 чаще выигрывают.

volatile не вариант, он может в некоторых компиляторах заставить переменную оказаться в памяти и не применять к ней оптимизаций вообще, что порождает некоторые косвенные эффекты, которые нам не нужны.
Во-первых, Вы не правы, в этом нетрудно убедиться самостоятельно, просто скомпилировав мою версию min и max для long long — там не будет ни одного условного перехода. И не должно быть. Во-вторых, при чём тут умножение, сложение и вычитание? И там тоже не будет условных переходов, если тип данных шире регистра, в этом тоже можно легко убедиться. В-третьих, Вы считаете, что я придумал себе врага и с ним борюсь. Ошибаетесь, я как раз ни с кем не борюсь, а всего лишь предложил пробный эксперимент, по результатам которого сделаю другой. Моё мнение по поводу компараторов вы вообще нигде здесь не увидите. Вот видите, Вы уже начинаете сыпать домыслами, когда выяснилось, что Вы подходите к дискуссии по вопросу не с того краю.
Что на что вы заменили? Опечатка, наверное?
Да нет, я бы не сказал: ) В научных вычислениях, когда попадаются задачи, занимающие миллионы часов машинного времени, такое тоже может иметь смысл.
Ещё дополню: когда говорите «никогда», то следует подчеркнуть, что речь идёт о типах данных вроде int, что не превышают по разрядности разрядность кода и для которых существуют нужные инструкции в процессоре. Например, если взять Ваш код для min/max и подставить туда long long, вы увидите в листинге несколько условных переходов, хотя только что говорили, что их НИКОГДА не будет для архитектуры x86. Поэтому предлагаю не тыкать друг друга носом в Стандарт и в опыт реальной работы, а смотреть на вещи как есть. Есть не мало случаев, когда «бинарный оператор» даёт условный переход, и это не только у дебилов, у нормальных программистов тоже бывает.
Так лучше. И не надо считать подобных программистов дебилами, потому что в отличие от перечисленных архитектур, существует масса других.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность