ducmatgoctoanlyhoa's blog

By ducmatgoctoanlyhoa, history, 2 months ago, In English

Hi! I am currently learning about pragmas in C++. I know that there are a lot of different pragmas you can do to speedup your program, e.g. #pragma GCC optimize("O3,unroll-loops") and #pragma GCC target("avx2"). However, I have some questions:

  1. When I include #pragma GCC target("avx2"), I get this error
In file included from C:/mingw64/include/c++/14.2.0/string:43,
                 from C:/mingw64/include/c++/14.2.0/bitset:52,
                 from C:/mingw64/include/c++/14.2.0/x86_64-w64-mingw32/bits/stdc++.h:52,
                 from c:\Users\minhduc\Documents\comp\596B.cpp:5:
C:/mingw64/include/c++/14.2.0/bits/allocator.h: In destructor 'constexpr std::__cxx11::basic_string<char>::_Alloc_hider::~_Alloc_hider()':
C:/mingw64/include/c++/14.2.0/bits/allocator.h:182:7: error: inlining failed in call to 'always_inline' 'constexpr std::allocator< <template-parameter-1-1> >::~allocator() noexcept [with _Tp = char]': target specific option mismatch
  182 |       ~allocator() _GLIBCXX_NOTHROW { }
      |       ^
In file included from C:/mingw64/include/c++/14.2.0/string:54:
C:/mingw64/include/c++/14.2.0/bits/basic_string.h:186:14: note: called from here
  186 |       struct _Alloc_hider : allocator_type // TODO check __is_final

What is weird is that the pragma works when I run it on a smaller file. E.g. this code runs perfectly well with no errors:

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2")
#include <bits/stdc++.h>
using namespace std;

int main() { cout << "idk"; }

but then this code doesn't (it throws that large error above):

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2")

#define __USE_MATH_DEFINES
#include <bits/stdc++.h>

#include <cmath>

#define endl '\n'
using namespace std;
using ll = long long;
using ull = unsigned long long;

const ll mod = 1e9 + 7, mod2 = 998244353, maxn = 1e6 + 1, maxn2 = 2e3 + 1;
// all the mods are primes!
template <typename T>
inline void dbgar(T *tr, ll n) {
    for (int i = 1; i <= n; i++) cout << tr[i] << ' ';
    cout << endl;
}

ll n, t, k, m, a, b, z, q, c, p, d;
long double g, u, w;
char ch;
ll ar[maxn], br[maxn], cr[maxn], dr[maxn];
string s, x;

int __tests__ = 1;
bool __MT__ = 0;

inline void preprocess() {}

inline void solve() {
    cin >> n;
    t = 0;
    z = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a;
        z += abs(a - t);
        t = a;
    }
    cout << z;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout << fixed << setprecision(20);
    preprocess();
    if (__MT__) cin >> __tests__;
    for (int __jiji__ = 1; __jiji__ <= __tests__; __jiji__++) solve();
    return 0;
}

I downloaded my g++ compiler from Winlibs, with version GCC 14.2.0 (with POSIX threads) + LLVM/Clang/LLD/LLDB 19.1.1 + MinGW-w64 12.0.0 UCRT - release 2 (LATEST), if it helps.

Does anyone know what is the problem? My laptop is rather new (and g++ -mavx2 <random file> works), so I doubt there's anything wrong with the instruction sets stuff. Also for the large code above the issue seems to be from the avx2 pragma line, as removing it makes the code work normally again. Does anyone have any idea what is the possible issue? Thanks in advance!

»
2 months ago, # |
Rev. 3   Vote: I like it +9 Vote: I do not like it

What is weird is that the pragma works when I run it on a smaller file.

That is because the error occurs with the code associated with the strings: In file included from C:/mingw64/include/c++/14.2.0/string:43

Smaller file doesn't use strings, but larger one has string s, x;

It is some bug inside standard library code. Codeforces G++20 и G++23 compiler versions have the same bug. Just include first, than use avx2 pragma. Or if you want this pragma to also affect code included from standard library, use:

#include <string>
#pragma GCC target("avx2")
#include <bits/stdc++.h>

My laptop is rather new, so I doubt there's anything wrong with the instruction sets stuff

If the compiler includes an instruction that your processor does not support when generating code, you will get a Runtime Error while executing this code, not a Compilation Error. This happens, for example, at Yandex.Contest, where quite old processors are installed on the testing machines.

  • »
    »
    2 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    So, basically use pragma after include

  • »
    »
    2 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    oh, thanks! I wonder why would including string before bits/stdc++.h makes the code not importing string again despite string being in bits/stdc++.h, but I assume that's probably due to optimization.

»
2 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Update: The issue seems to be there, even with non-avx2 optimizations. In detail, any of the following pragmas generate that same error:

  • #pragma GCC target("avx")
  • #pragma GCC target("sse4.2")
  • #pragma GCC target("popcnt,lzcnt")
  • #pragma GCC target("fma")