Блог пользователя MegaEnderman2009

Автор MegaEnderman2009, история, 6 месяцев назад, По-русски

Почему некоторые решения работают значительно быстрее при использовании разных компиляторов С++? Так, решая 1800F - Dasha and Nightmares
я столкнулся с тем, что при использовании компилятора 20-й версии решение не проходит по времени, при этом выполняется в итоге за примерно 4200мс, в то время как 17й компилятор справился с решением в среднем за 3650мс, отсюда вопрос почему? Само решение оно вот https://mirror.codeforces.com/contest/1800/submission/241615256 , у меня было предположение что это связано с прагмой на avx инструкции, но мимо, без нее решение работает аналогично по времени, может кто-то знает в чем дело и что именно 17й компилятор делает быстрее, и соответственно, когда его лучше использовать?

  • Проголосовать: нравится
  • -4
  • Проголосовать: не нравится

»
6 месяцев назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Ну, конкретно здесь разница в памяти (в блоге стоило отметить, что С++17 в твоей посылке 32битный, соответственно, все указатели в STL сущностях "весят" в 2 раза меньше), а в целом отличие в $$$15$$$% рантайма не кажется чем-то странным, так бывает и в пределах одного компилятора.
Насчет avx2: она здесь бесполезна — такие прагмы нужны, если хочется векторизовать какой-то код с простым скалярным содержимым, а у тебя все циклы плохо векторизуемы (везде обращение к каким-то объектам STL, ифы)... И, да, 0fast гораздо чаще замедляет код, чем ускоряет его (например, твой же код без этого работает чуть быстрее 241617897).
Скажу ещё, что прагмы — последний рубеж оптимизации, в твоём случае можно было бы попробовать сначала избавиться от push_back (ты же знаешь, что размер будет $$$n$$$), заменить std::vector фиксированного размера $$$26$$$ на std::array<int, 26>, который быстрее хотя бы потому, что аллоцируется не на куче, а на стеке. Возможно, хешировать пары можно так, чтобы побыстрее было (ксор вообще довольно странный выбор, обычно берут линейную функцию от хеша первого и второго элементов)

  • »
    »
    6 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Понял, спасибо, интересное решение с использованием масства вместо вектора, но разве тогда не лучше вообще использовать обычный сишный массив int a[26]?

    • »
      »
      »
      6 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Разница с сишным массивом будет косметическая (если вообще будет) -std::array<T, n> на самом деле — просто довольно легковесная надстройка над T[n], и с ним удобно работать в силу того, что это всё же часть STL (например, в твоем случае std::vector<std::array<int, 26>> выглядит довольно прозрачно, а в случае сишных массивов.. std::vector<int*>(?) — как-то стрёмно.
      Ну и да, на самом деле конструкция int a[n] вне глобальной области видимости (т.е. внутри какой-то функции) запрещена стандартом, и я, если честно, не знаю, что происходит потом с памятью, т.е. как она высвобождается.
      Мораль такая, что если нужно именно пихать, то std::array<T, n> можно заменить на T[n], да, но это примерно такая же крайность, как прагмы, IMO))

      • »
        »
        »
        »
        6 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Ну в целом да, я если честно не разбираюсь в пропихмвании, прагмах и тп, за все время прям пихать раз 5 приходилось от силы, с учетом задач с других сайтов