Pull to refresh
1
0
Калмыков Юрий @Videoman

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

Send message
2 дня назад — первый релиз? поздравляю)
:) ну да, действительно, выглядит как-будто либу в ответ на комментарий настрочил. На самом деле она в продакшене используется уже пару лет, а вот протестить под несколько платформ, оформить и т.д. — руки могут год не доходить.
Пойду пару советов в issue закину
Спасибо, осмыслю тогда и отвечу, что бы не плодить офтопик тут.
Кстати, полностью поддерживаю сарказм. Вроде как сначала имели конвертеры в стандарте, потом в С++17 их вдруг задепрекейтили, без объяснений. Ничего нового не завезли. С u8"" строками вообще не понятно. Допустим до С++20 в качестве контейнера для UTF-8 я могу использовать std::string и u8"" строки, которые сейчас преобразуются к char. Интересно, как предполагается работать с UTF-8 в дальнейшем, когда у нас появляется тип char8_t, что с обратной совместимостью к тоннам уже существующих API?
Пока приходится пользоваться своим велосипедом: sutfcpplib, но почему-то ничего готового не появляется в стандарте, хотя бы базовые вещи :(?
По своей практике, могу сказать что отказ от буферизации на скорость записи не влияет, либо влияет в меньшую сторону. Да и заменить одно на другое не так просто. Это все-равно что поменять I/O API. Не буферизированный вывод, это работа со строго выровненными блоками данных, где всю работу кеша мы берем фактически на себя. Это всё скорее про случаи где важна надежность, чем скорость.
А мета-информация, например запись о длине файла и т.д.? Не знаю как под Linux, но под Windows также возможна запись без буферизации однако, что бы обновить размер файла, всё равно придется вызывать FlushFileBuffers (fsync).
А если будет, то вместо создания local_variable компилятор сразу создаст result конструктором по умолчанию в точке вызова функции f(). А функция f() будет выполнять действия сразу с переменной result.
Попытка максимально упростить описание может привести к неправильному понимаю того, что на самом деле происходит. На практике компилятор просто выделяет память под объект, никакого конструктора по умолчанию не вызывается (его вообще может не быть), а объект создается уже поверх выделенной памяти внутри функции, в которую передается указатель на выделенную память, тем конструктором, который используется в RVO.
Вот пример:
#include <iostream>

class A
{
public:

    A() noexcept  { std::cout << "A()"; }
    A(const A& that) = delete;
    A(A&& that) noexcept = delete;
    A(int x, int y) noexcept : x(x), y(y) { std::cout << "A(int, int)"; };

    A& operator=(const A& that) = delete;
    A& operator=(A&& that) noexcept = delete;

    int x;
    int y;
};

A func(int x, int y) {
    return A(x, y);
}

int main()
{
    A a = func(5, 5);

    return a.x + a.y;
}
Спасибо большое за ссылку. Меня конечно больше интересует состояние дел на текущий момент, после безумного роста на видеокарты, а не в 2020 году. Так-то мы раньше вообще использовали гибридные решения, где в сервере было и то и то. Одно время NVIDIA была даже предпочтительнее, так как одно время на серверных Xeon-ах почему-то был заблокирован HD Graphics. Хотелось бы конечно сравнение в текущих ценах (2022 год).
… только для односокетных конфигураций
Я имею в виду поставить несколько юнитов целиком, с материнской платой и CPU с встроенным Quick Sync модулем, даже не обязательно серверного класса.
MediaSDK под Linux, или всё слишком замудрёно стало с версиями драйверов
С конфигурации под Linux я на практике не сталкивался, только под Windows. Но даже с учетом лицензии Windows, цена нескольких хостов для кодирования H.264, мне кажется может оказаться дешевле. Отсюда и вопрос.
Спасибо большое за обзор. Есть такой вопрос: с учётом несколько не гуманной стоимости плат NVIDIА, да той же RTX A5000, вы не проводили эксперименты, не получится ли дешевле поставить 4-6 CPU с аппаратным ускорением кодировки H.264, например от Intel, c Quick Sync на борту?
Сигнатура subb() c constexpr включает в себя случай subb() c inline. Компилятор может вычислить результат constexpr функции во время компиляции, а может просто оставить вызов как обычной функции, которая будет вычислена в рантайм. Всё это зависит от контекста вызова, так что я не представляю какую перегрузку он должен был бы выбрать.
Хорошо. Давай теперь посмотрим к чему приведет ваше решение, а скорее не решение, а заметание проблемы под ковёр:
  1. В данном случае это библиотека и мы тем более не должны выносить сложною на ваш взгляд логику наружу и перекладывать возможность ошибки и неправильного использования на пользователя библиотеки. Полезность библиотеки от этого будет только страдать.
  2. Теперь эти два класса нельзя будет использовать в constexpr коде, так как мы не контролируем внешний код и не знаем в каком контексте наш класс будет использоваться.
  3. Пользователь библиотеки будем вынуждены менять весь свой код во время разработки, если в коде будет меняться контекст использования класса, то constexpr, то runtime.
  4. Во внешнем коде будет расти комбинаторные сочетания вспомогательных функций, так как мы будем вынуждены преобразовывать один класс в другой, передавать эти два класса как параметры в разных сочетаниях. Это можно легко представить на таком примере: представьте что у вас std::vector не может быть константным, а вместо этого будет отдельный класс std::const_vector — как же удобно будет ними двумя работать и как быстро вы получите комбинаторный взрыв ?!

В общем я пожалуй останусь при своём мнении, что std::is_constant_evaluated() это меньшее из многих зол и при уместном использовании позволяет быть коду надежнее, проще и гибче, а следовательно полезная и нужная функция.
Не могли бы вы развернуть свой вопрос, ничего не понятно?
constevalЭто то же почти тоже самое что и constexpr, только функция должна работать только в режиме компиляции. Если функция в заданном контексте не может быть вызвана во время компиляции, то это приведет к ошибке компиляции.
В том то и проблема, что constexpr не входит в тип функции и по нему не возможна перегрузка. Это не тоже самое что спецификация const в конце метода класса.
Отлично, согласен! Заодно может быть вы поможете мне решить вполне практическую задачу. Я вам буду премного благодарен. Поехали! Есть класс: long_uint.h: line 43
template<typename native_t, uint_t size>
class long_uint_t<native_t, size>;
Класс реализует арифметику над длинными целыми, в том числе во время компиляции. Нам сейчас не важны все операции возьмем один оператор — меньше (<): long_uint.h: line 279
template<typename native_t, uint_t size>
constexpr bool long_uint_t<native_t, size>::operator<(const long_uint_t& that) const noexcept
{
    native_t digit = digits[0];
    bool borrow = sub(digit, that.digits[0]);

    for (uint_t n = 1; n < std::size(digits); ++n) {

        digit = digits[n];
        borrow = subb(digit, that.digits[n], borrow);
    }

    return borrow;
}
Реализация у него в виде шаблона и очень простая: вычитаем из первого аргумента второй и если произошел перенос в старшем бите, то первый аргумент меньше. Само вычитание c переносом реализовано через функцию subb (Subtract with borrow): long_math.h: line 437. Функция subb() полностью платформонезависима и без проблем работает в constexpr выражениях:
template<typename type_t, std::enable_if_t<is_unsigned_v<type_t>, int>>
constexpr bool subb(type_t& value1, type_t value2, bool borrow) noexcept
{
    type_t tmp = value1;
    value1 -= value2;
    bool borrow_new = value1 > tmp;
    tmp = value1;
    value1 -= borrow;
    borrow_new = borrow_new || (value1 > tmp);

    return borrow_new;
}
Дальше, на некоторых платформах, например Windows, мы можем выполнять данную операцию намного эффективнее для 32-х битных беззнаковых целых, делаем перегрузку: long_math_msvc.h: line 372
inline bool subb(uint32_t& value1, uint32_t value2, bool borrow) noexcept
{
    return _subborrow_u32(static_cast<uint8_t>(borrow), value1, value2, &value1);
}

И вот тут у нас проблема, перегрузка как раз и является частным случаем реализации которая невозможна для функций исполняющихся на этапе компиляции. В данном случае, так как запрещено использование интринсиков совместно с constexpr функциями.
Как бы нам тут могла помочь std::is_constant_evaluated(): мы могли бы реализовать две разные функции subb_constexpr() и subb_runtime() и вызывать одну либо другую в зависимости от контекста:
template<typename type_t, std::enable_if_t<is_unsigned_v<type_t>, int>>
constexpr bool subb(type_t& value1, type_t value2, bool borrow) noexcept
{
    return std::is_constant_evaluated() ? subb_constexpr(value1, value2, borrow) : subb_runtime(value1, value2, borrow);
}

Как это сделать без std::is_constant_evaluated() я не знаю. Какие ваши предложения?
Просто написать две разные функции.
Функции физически разные, но одна должна являться перегрузкой другой, т.к. они вызываются в одном и том же контексте, в зависимости от шаблонного параметра и режима выполнения (constexpr). Можете привести пример С++ кода который так может без std::is_constant_evaluated?
Я бы сам хотел что бы компилятор всё оптимизировал за меня и сам обо всём догадывался, но ресурсы и память компилятора не бесконечны, к сожалению.
Если реализации сильно отличаются, то, возможно, им просто не место в одной функции.
Речь не идет о том что бы всё помещать в одну функцию конечно, но в любом случае есть точка принятия решения и её не реализовать без std::is_constant_evaluated().
ИМХО std::is_constant_evaluated() — костыль с жутко неинтуитивным поведением. Ситуации, описанные в пропозале, который я читал года три назад, выглядят какими-то уж больно натянутыми, и мне при всей моей любви к компилтайм-упарыванию ни разу не хотелось этой функцией воспользоваться.
Предположим у вас есть шаблонная функция, которая вас устраивает во всех ситуация, в том числе в constexpr режиме. Теперь, предположим, что в случае если шаблонный параметр является целым, кратен 4-м байтам и код выполняется в рантайме, вы можете сильно оптимизировать алгоритм на GPU или ещё как-нибудь. Какое ваше предложение, что делать?
Почему все функции не могли бы быть implicitly constexpr, непонятно.
… в Комитете сидят либо напрочь оторванные от практики люди, либо психопаты, ненавидящие программистов.
Как не парадоксально, но может оказаться совсем наоборот — эту фичу пилили какие-нибудь практики, которые решали свою, сугубо локально задачу, которые были так этим заняты, что у них не было уже сил поднять голову и осмотреться по сторонам. Об этом косвенно свидетельствует наличие проблемы на которую я наткнулся в своём пет-проекте. Вот как можно было в стандарте зафиксировать, что constexpr метод может отработать во время компиляции, а может и не отработать, но при этом не подумать, что бывает что реализации существенно отличаются и не дать инструментов которые дали бы возможность определить в каком режиме сейчас находится код ?! И только в С++20 вдруг очнулись и добавили std::is_constant_evaluated().
Судя по тому, что у функции модификатор const это мембер класса и смысл в static как раз может быть, а вот constexpr и так автоматом делает такую функцию inline. Т.е. как раз inline тут лишний.

Information

Rating
5,247-th
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity