Спасибо за интересную информацию. Ну вообще-то параллельная работа двух разных видеокарт достаточно ожидаема, было бы очень странно, если б они мешали друг другу. А такой режим может оказаться актуальным, если надо параллельно обрабатывать несколько 4K потоков.
Статья как раз про декодеры. Исторически сложилось так, что всю жизнь сидел на Intel. С NVIDIA также работал мало. А вот с продукцией AMD практически не имел дела. Про поддержку Radeon в ffmeg вообще не слышал, специально не искал, так как эта поддержка для меня не актуальна.
Спасибо! Очень интересная информация. Исторически сложилось так, что я всю жизнь сидел на Intel (да и сейчас сижу). Было бы очень интересно пощупать AMD, но в обозримом будущем наверное не получится (хоть они и 5 рублей за кило).
Могу сразу сказать, что libx264 и libx265 грузят ЦП на 100%, то есть они без лишних просьб используют все потоки. Аппаратное ускорение они не поддерживают. Кодеры *_qsv работают. (Наверное и их аналоги от Nvidia.) Главная проблема в том, что для кодеров используют большое число параметров, которые влияют на скорость кодирования и надо перебирать все комбинации, так, что подобные таблицы могут быть огромными. Даже если использовать только пресеты (ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow), все равно будет очень много данных.
По поводу Третье место: «Неуловимое исключение». Всегда был уверен, что любые ошибки приватного наследования обнаруживаются на стадии компиляции. А тут такое. Проверил в MSVS. Если поставить в конце catch(…), то catch(std::exception&) молча пропускается, перехват в catch(…). Если убрать catch(…), то в debug возникает abort, в releast ничего. Стало быть полная статическая типизация при перехвате исключения невозможна. Очень полезная информация.
Для меня метки времени одна из самых таинственных частей ffmpeg. То, что я написал базируется на экспериментах, в сомнительных случаях я просто тупо вывожу метки в лог.
Интересно, когда все эти радости начнут поддерживать популярные компиляторы. Судя по поддержке С++11/14/17 как раз где-то к 2023 году. А до этого останется только обсуждать все это в блогах. И ведь еще дожить надо.
Спасибо! Я с этим аспектом проблемы глубоко не разбирался, хотя призывал программировать без предупреждений почти в каждом раздела. Но замечу, что это флаги GCC, в других компиляторах по другому. И с таким количеством флагов работать не очень удобно. Считаю, что лучше, если программист распознает эти проблемы «в лицо», то есть видит в коде, а еще лучше, если сразу пишет правильный, более безопасный код.
Хочу еще раз обратить внимание, что никакой агитации за C# нет, просто хотелось показать, за счет чего, весьма близкий язык является более надежным и удобным. Сам я пишу на C++/C# где-то 50 на 50 уже много лет, и люблю оба языка. Считаю, что C++ программисту весьма полезно знать C# (ну на худой конец Java).
Нет. Это язык со статической типизацией, но она не строга ни в смысле гарантий, ни в смысле выразительности.
Статическая/динамическая типизация и строгая/нестрогая типизация это разные критерии классификации типизированных языков. Сильная типизация выделяется тем, что язык не позволяет смешивать в выражениях различные типы и не выполняет автоматические неявные преобразования. C++ спроектирован как язык со строгой типизацией, но с рядом послаблений в виде implicit conversions, из-за чего его чисто формально можно отнести к языкам с нестрогой типизацией. Вот статья на эту тему.
Так и не понял, что именно тут плохо. Какие-то общие слова, что можно делать ошибки. Так, наверное, можно вообще про любую языковую фичу написать в любом языке.
Программист может написать такие перегрузки, что потом будет пол дня думать, как они будут разрешатся в том или ином контексте. Я рекомендую так не делать. Потом перегруженные функции затрудняют анализ кода, особенно чужого, с помощью текстового поиска.
В C#, кстати, есть rvalue-ссылки и вообще move semantics?
Этого в C# нет.
То есть, если вы пишете управляющий ресурсом класс, то его, внезапно, надо сесть и писать. Нетривиальный вывод!
Не совсем понял, в чем суть возражения. Про классы, управляющие ресурсами у меня большая статья.
Неверная логика. Инициализация нулями не нарушает гарантий, даваемых С. Дело скорее в производительности.
Я как раз и имел в виду производительность.
Не понял логики. А как же порядок объявления членов?
В C# при создании объекта сначала инициализируются все поля объекта (значениями, заданными при объявлении или по умолчанию), затем вызывается конструктор базового класса или перегруженный конструктор, если они указаны в списке инициализации, затем сам конструктор.
Только это всё же не совсем то. Начиная с C++11 статик-переменные уровня функций инициализируются потокобезопасно, что, конечно, хорошо, но ведёт к очевидной дополнительной плате на синхронизацию при каждом входе в такую функцию.
За все надо платить. Но в данном случае немного, такой вызов обычно происходит один раз.
Не использовать сырое new. 2018 год на дворе уже, ё-моё.
Конечно, new/delete должны быть максимально инкапсулированы. Но полностью избавится от них не реально. C++ программист должен четко знать, как с ними правильно работать.
Использовать make_unique и make_shared.
Помогает, но не всегда. Эти шаблоны не позволяют использовать пользовательские удалители, и в этом случае придется работать с сырыми указателями и надо знать, как правильно писать выражения без потенциальных утечек памяти.
Судя по общему тону до этого, считается, что это в C# сделано типа хорошо?
Тут я выразился не совсем точно. Описываю ситуацию более подробно. Пусть в C# у нас есть базовый класс и производный. При создании экземпляра производного класса сначала инициализируются все поля базового класса и затем все поля производного. Только после этого вызывается конструктор базового класса и потом конструктор производного. Пусть в базовом классе определена виртуальная функция и она переопределяется в производном. Если в конструктор базового вставить вызов этой виртуальной функции, то вызовется переопределенная, соответственно, для объекта у которого уже инициализированы поля, но еще не вызывался конструктор. Довольно забавно. Если четко понимать, как это работает, то можно использовать.
В C# программист тоже может сделать в unsafe-блоке какую-нибудь ерунду, разве нет?
Программист пишет unsafe-блоки на свой страх и риск. Почти все гарантии .NET отменяются.
Да и говорить о сборщике мусора как о спасении от «значительной части» проблем, как будто единственный существующий ресурс — это память, ну очень примитивно.
Я же не говорил «всех проблем». Для оставшихся проблем есть интерфейс IDisposable. Конечно, работать с ним не так удобно, как с деструкторам в C++.
Согласен, что в C++ много еще более тонких моментов. Я описал базовые проблемы. Еще раз, никакой агитации за C# нет, хотелось показать, за счет чего весьма близкий язык является более надежным и удобным. Лично я считаю, что C++ программисту весьма полезно понимать как работают платформы .NET или Java. Большинство примеров не притянуто за уши, я натыкался на них в коде коллег (включая самого себя).
Ну корни у меня самые, что ни на есть плюсовые, с 90х. С++ я люблю и пишу на нем постоянно уже десятки лет. Моя цель — обратить внимание на проблемные моменты программирования на С++, которые легко могут привести к ошибкам. Программисты должны помнить об этих проблемах, не терять бдительности и при необходимости принимать необходимые меры. Никакой агитации за C# нет, просто хотелось показать, за счет чего, весьма близкий язык является более надежным и удобным. В целом стиль отзыва выглядит сумбурным, если не сказать истеричным. Практически ничего по существу ответить нельзя, так как никакой существенной критики нет, сплошные вопли.
Если программисту нужно совпадение строк, то правильным будет правое выражение, но по ошибке он может написать левое и получит результат с точностью до наоборот, условие будет верным, если строки не совпадают.
Ну может пример не совсем удачный. Но суть в том, что разработчики и пользователи интерфейса не всегда могут знать контекст реализации и константность может добавить дополнительные проблемы при реализации интерфейса, например вынудит использовать mutable. Вообще я планирую написать статью про константность в C++.
Stream #0:0: Video: h264 (High), yuv420p(progressive), 3840x2160 [SAR 1:1 DAR 16:9], 30.30 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
ffmpeg -c:v h264_qsv -i INPUT -f null — -benchmark
на выходе
frame= 2241 fps=129 q=-0.0 Lsize=N/A time=00:01:14.77 bitrate=N/A speed=4.3x
Загрузка ЦП — 35%, графический процессор — 80%
Статическая/динамическая типизация и строгая/нестрогая типизация это разные критерии классификации типизированных языков. Сильная типизация выделяется тем, что язык не позволяет смешивать в выражениях различные типы и не выполняет автоматические неявные преобразования. C++ спроектирован как язык со строгой типизацией, но с рядом послаблений в виде implicit conversions, из-за чего его чисто формально можно отнести к языкам с нестрогой типизацией. Вот статья на эту тему.
Программист может написать такие перегрузки, что потом будет пол дня думать, как они будут разрешатся в том или ином контексте. Я рекомендую так не делать. Потом перегруженные функции затрудняют анализ кода, особенно чужого, с помощью текстового поиска.
Этого в C# нет.
Не совсем понял, в чем суть возражения. Про классы, управляющие ресурсами у меня большая статья.
Я как раз и имел в виду производительность.
В C# при создании объекта сначала инициализируются все поля объекта (значениями, заданными при объявлении или по умолчанию), затем вызывается конструктор базового класса или перегруженный конструктор, если они указаны в списке инициализации, затем сам конструктор.
За все надо платить. Но в данном случае немного, такой вызов обычно происходит один раз.
Конечно, new/delete должны быть максимально инкапсулированы. Но полностью избавится от них не реально. C++ программист должен четко знать, как с ними правильно работать.
Помогает, но не всегда. Эти шаблоны не позволяют использовать пользовательские удалители, и в этом случае придется работать с сырыми указателями и надо знать, как правильно писать выражения без потенциальных утечек памяти.
Тут я выразился не совсем точно. Описываю ситуацию более подробно. Пусть в C# у нас есть базовый класс и производный. При создании экземпляра производного класса сначала инициализируются все поля базового класса и затем все поля производного. Только после этого вызывается конструктор базового класса и потом конструктор производного. Пусть в базовом классе определена виртуальная функция и она переопределяется в производном. Если в конструктор базового вставить вызов этой виртуальной функции, то вызовется переопределенная, соответственно, для объекта у которого уже инициализированы поля, но еще не вызывался конструктор. Довольно забавно. Если четко понимать, как это работает, то можно использовать.
Программист пишет unsafe-блоки на свой страх и риск. Почти все гарантии .NET отменяются.
Я же не говорил «всех проблем». Для оставшихся проблем есть интерфейс IDisposable. Конечно, работать с ним не так удобно, как с деструкторам в C++.