Comments

I'm sorry I forgot to test this earlier. Indeed, %Lf doesn't work with long double, nor does std::int and std::cout. At least the long double type works fine for computations and usage; it is a functioning extended floating-point type. When outputting, converting it to double seems to work just fine.

However, when I tested other environments that use libc++, such as Ubuntu 24.04 with libc++-dev installed via apt install libc++-dev, no issues were inputting/outputting long double types when specifying -stdlib=libc++ for clang. So it's a mingw-libc++-specific issue I guess.

Since you've chosen MSYS2 as the distribution for installing GCC, why not try installing pacman -S mingw-w64-ucrt-x86_64-clang while you're at it? The clang installed this way will default to using the libstdc++ library that mingw-w64-ucrt-x86_64-gcc uses and benefiting from LLVM's optimization capabilities, it might offer better performance, especially in terms of time consumption.

However, the mingw-w64-ucrt-x86_64-toolchain does not support sanitisers. In my local experiments, I found that if you want to restore "clang diagnostics" without upgrading MS Visual C++ 2022, you can use another branch under MSYS2: mingw-w64-clang-x86_64-toolchain. This clang will utilize the libc++ library and allow you to use -fsanitize=address,undefined for diagnostic hints. The only downside seems to be the lack of the precompiled header file "bits/stdc++.h".

So does the MSC++ (MSVisualC++), which has disappeared since the MSVCRT event.

This release also includes Clang/LLD/LLDB 18.1.8, which might not meet the performance downgrade. Would we have a chance to test the clang compiler?

Also, it is easy to make the Clang use existing MSVC toolkits, by passing --target=x86_64-pc-windows-msvc and it would search and use MSSTL.

No, it's not fixed at least for C++.

My further tests show that the bug is just hidden somewhere else. Need some other methods for this bug. See my test and conclusions.

Auto comment: topic has been updated by tatianyi (previous revision, new revision, compare).

Months later, CodeForces upgraded its system to Windows Server 2022, meaning that it is finally possible to upgrade almost everything.

The .NET8 supports the AOT technology which could accelerate C# codes to the native level. Although .NET6 is a relatively new LTS version, There's no reason not to upgrade .NET in the future.

The easiest way to avoid it is to remove those pragmas, especially "target" directives. It's a bug affecting every GCC13 on any platform, and Clang if it's using GCC13's libstdc++.

C++ is the tier-0 fast language for competitive programming in Codeforces, I think it's not particularly useful to do so when this language already has a big advantage over others.

UPD: It's not fixed at least for C++.

Further investigation shows that the bug is just hidden somewhere else. Need some other methods for this bug. See my test and conclusions.

Original post↓


It is fixed by updating the system to Windows Server 2022, those legacy 32-bit compilers seemed to benefit from this (you can try copying 253400416 to custom test, and TLE would not happen). As MikeMirzayanov said, they are working on resolving the situation more systematically.

MikeMirzayanov did not reveal how they fixed the problem, but I suppose they also migrated the 64-bit compilers to the UCRT version of the mingw64 toolchain.

On orz → C++20 is back, 3 years ago
0

I'm just a Windows user and rarely use Linux. It's my fault that I didn't read the doc thoroughly, and compile and build the libc++ myself. For me, I usually don't compile those libs. Instead, I tend to use existing packages. I install the MSC++ and clang-cl using VCInstaller, and install the MinGW clang using msys2-mingw-w64-ucrt toolchain which acts like a "Linux environment" that comes with GCC by default.

The latter is way much easier than building with CMake. Thus, it naturally comes with libstdc++ as it's bundled with GCC toolchain and library. On the other hand, if you try to sync with CodeForces' language config (I mean, see the word "winlibs" in that quote), you could download the GCC + LLVM/Clang/LLD/LLDB release, which is similar to the aforementioned "msys2-mingw-w64-ucrt" version.

In this case, I used your code and compiled it with the -Wall flag. It does generate a warning message, and the #pragma GCC directive is ignored, the executable sizes are the same here. Seems like I made a bit of a serious error in my testing. I'm sorry.

Although users can not use the pragma directive to enable O3 optimization, the O2 for clang is already nice enough for competitive programming. I'm not saying that clang O2 is necessarily better than GCC O2 or even O3. After all, this thing isn't absolute as we encounter different results. It's enough for this use, I think.

Apart from that, as for the __int128 problem, I simply added unsigned __int128 x; line and it successfully compiled. However, for this code you mentioned,

#include <limits>
#include <type_traits>

using uint128_t = __uint128_t;

int main()
{
    static_assert(std::is_unsigned<uint128_t>{}, ""); 
    static_assert(std::is_integral<uint128_t>{}, "");
    static_assert(std::numeric_limits<uint128_t>::digits == 128, "");
}

it failed to compile both for MinGW clang and MinGW GCC(11.4 and 13.2, ucrt).

Clang

Even unexpectedly, on some online compilers like Customtest of CodeForces and Godbolt, it still failed to compile.

GCC

As far as I tested, only GCC 12.2 on AtCoder could pass this code. It's confusing and may come with some additional compile flags that control those behaviours.

On orz → C++20 is back, 3 years ago
+2

The new Windows Server 2022 is deployed already.

You can use the code in custom test to get info about the system:

For Windows only

And now the output is

===OS information===
Windows Server 10.0.20348
===CPU information===
Intel(R) Core(TM) i3-8100 CPU @ 3.60GHz
===Memory information===
total 15.86 GB (8.88 GB available)
On orz → C++20 is back, 3 years ago
0

Well, in my simple tests, things don't seem to be the same as you say. The clang on Linux or Windows is usually bundled with libstdc++; it seems that only on MacOS is the clang by default bundled with libc++.

The bad performance of many STL implementations of libc++ is surely concerning. I got to know that for C++17std::gcd on Apple Clang's libc++, it would use the Euclidean algorithm instead of Stein's.

However, as for me, I can hardly use libc++ for clang on Windows. I tried to install and configure that but failed. The result is, that I can only use clang-cl or MinGW clang version, whose default configuration is using msSTL or MinGW libstdc++.

In my test case, the clang-cl that uses msSTL would report warning: unknown pragma ignored [-Wunknown-pragmas], but the MinGW clang doesn't. It does use MinGW libstdc++, but in my point of view, it is compatible with almost all GCC's compiler features and library features.

So as a newbie participant, in my point of view, I still hold the point that for competitive programming, the MinGW clang is almost no different in the usage experience, even the clang-cl would have better performance than the "default" libc++ clang. Maybe what you are concerned about would not appear on the Windows platform with those two versions?

On orz → C++20 is back, 3 years ago
+5

The clang++ is just a compiler frontend that doesn't come along with an STL implementation. On Windows, it could use MSC++'s MSSTL, or use MinGW64-UCRT's libstdc++. I would call the former "clang-cl", and the latter "MinGW clang".

The clang-cl would be compatible with most MSC++ compile commands, and MinGW clang would be compatible with most GCC compile commands. MikeMirzayanov didn't mention which clang would be migrated to (or both?). If it's clang-cl, almost all the behaviour would be as similar as MSC++ (except VLA extension), such as 64-bit long double type, using std::_Signed128 instead of __int128 for 128-bit integers support, lack of some builtin functions like __lg (although it can be replaced by C++20 std::bit_width(x)-1), etc.

However, clang could manually set its compile target to MinGW, or automatically do this if it's installed with MinGW (e.g. the packed one with winlibs, currently it provides clang17 with UCRT and clang18 with MSVCRT, but clang18 with UCRT may be coming soon). In this case, all headers that libstdc++ has could be used normally, even with full precompile header bits/extc++.h, and other behaviour would be compatible with GCC, like #pragma GCC with the usage of optimization pragmas, and __int128 and 128-bit long double and more. It's so compatible that you could hardly notice that you are not using GCC.

Although GCC is much more thoroughly tested as so many OJ are using this, Clang would have a much more aggressive optimisation and better performance due to many tests of participants (say, much faster or even TLEs become ACs after switching GCC to clang on Atcoder). What's more, both clang-cl and MinGW clang have the almost same optimisation ability for my test codes on Windows, thus is no worry about its code generation. And of course, it makes sense to add both compilers and let users decide.

No. See ToxicPie9's test code:

#include <iostream>
#include <windows.h>

using namespace std;

void *alloc(size_t s) {
    printf("");
    auto p = (void *)HeapAlloc(GetProcessHeap(), 0, s ? s : 1);
    asm volatile("" ::"r"(p));
    return p;
}

void dealloc(void *p) {
    HeapFree(GetProcessHeap(), 0, p);
}

int main() {
    int evil = 12495;
    int count = 1e6;
    for (int i = 0; i < evil; i++) {
        alloc(0x28);
        dealloc(alloc(0x1c));
    }
    for (int i = evil; i < count; i++) {
        dealloc(alloc(0x1c));
    }
    cout << "hi\n";
}

It takes about 9 seconds on the CF custom test, while testing this code locally using UCRT mingw64 gcc13.2, it takes no time, showing that this version is still the buggy MSVCRT one.

Maybe not, because UCRTmingw64 gcc13.2 and msvc2022 would not trigger this weird 9s bug. But the MSVCRTmingw64 gcc13.2 (including the one recently back) would do.

The code is pretty neat.

Meanwhile, I found something similar to your implementation: the std::_Signed128 and std::_Unsigned128 in MSC++2019, which may be a firm reference for implementing signed __int128.

LL operations in the 32-bit environment are much slower than expected because there is no x64 CPU instruction nor registers to use. In that case, the 32-bit compilers could only simulate the x64 code by taking the data apart (high 32 bits and low 32 bits), calculating those parts individually (without efficient instructions either), and putting it back together.

If the code depends heavily on LL type, it could highly TLE as those operations aforementioned are too slow. Also, this TLE on the editorial reflects that the proposer of this question may not have thought about other programming languages (especially those non-compile-based). They were too focused on the details of efficient algorithms and ignored the constant-level effects of the environment/different languages.

Fun fact: LL type in 32-bit compilers may be a typedef of __int64.

Not only C++20(64) but also other compilers using MSCVRT, along with MSC++2017.

Switching the whole server to Linux is not as easy as upgrading it to later Windows versions. If CF would install an update to obtain UCRT or just simply switch to Windows10/11 or Winserver2016/2019/2022, it could prevent those bugs from happening by using UCRT-based mingw64 version of GCC, Clang and MSVC compiler instead of using MSVCRT version.

What's more, the "scanf-performance" in those MSVCRT 64-bit compilers is significantly worse than cin without tie and sync.

See 240611683 that takes 1013ms to run, TLE if used scanf; 32-bit version 240612877 takes 1500ms to run, almost the same run time if used scanf.

As an alternative, you can use std::make_heap, std::push_heap and std::pop_heap which use a (sub)range of STL containers (e.g. vector) to construct a heap in place:

int main() {
	std::vector<int> v1{ 3, 2, 4, 1, 5, 9 };
	std::make_heap(v1.begin(), v1.end()); // 9 5 4 1 2 3
	std::pop_heap(v1.begin(), v1.end());  // 5 3 4 1 2 9
	auto top = v1.back();    // 9
	v1.pop_back();   // 5 3 4 1 2

	std::vector<int> v2{ 3, 2, 4, 5, 9 };
	std::make_heap(v2.begin(), v2.end(), std::greater<>{}); // 2 3 4 5 9
	v2.push_back(1);	// 2 3 4 5 9 1
	std::push_heap(v2.begin(), v2.end(), std::greater<>{});  // 1 3 2 5 9 4
}

These functions also have their C++20 "std::ranges" version like std::ranges::make_heap(v); though, albeit the C++11 version is already not so difficult to use.

but these two are already added in STL with C++17

The Visual Studio on CodeForces itself remained in a considerably old version (VS2017 32-bit) because the system that CodeForces uses is Windows 7 (or… Windows Server 2008?) which may be difficult or even cannot upgrade to any newer version!

Due to the same reason, the .NET8 cannot be installed on CF, its minimum system requirement is Windows 8.1 (or Windows Server 2012 R2).

Thus, unless CF upgrade itself to Windows Server 2022 or newer, we can neither see MSC++latest(VS2022 64-bit) nor C#12 in the language list. The latest version of MSC++ can be VS2019 with full C++20 and C++latest (a bit newer than C++20) 64-bit target output. The .NET, however, version 6.0 is both the latest and LTS one CF can support.

Maybe you can contact Vladosiya for more info? I'm just a common newbie participant without such lang-tune-experience.

In Visual C++ 2019 or later versions, you can use the header #include <__msvc_int128.hpp>. This header brings two class types, std::_Signed128 and std::_Unsigned128, which also come with operands like +-*/ and some bitwise operators.

If you take a peek into this header, you will see the line:

uint64_t _Word[2];

and that's how they store an int128 number.

It seems that there is no built-in conversion function for these class types, so you may have to use _Word[x] to "truncate" half of it.

This thread from the MS developer community discussed the VC++ support for 128-bit integer type, and after this port, you can add it with any supported C++ standards. Source code of this header.

About non-trivial floating-types, the C++23 standard header #include <stdfloat> in Visual C++ 2022 says:

// We don't support any optional extended floating-point types, but we do need to provide an empty `namespace std`.
// We don't need to `export` it for modules, as the other headers will implicitly do so (N4950 [module.interface]/2.1).

However, according to the standards, these headers and other extended floating-types are supposed to be optional. Oops.

In my opinion, the compiler "Microsoft Visual C++ 2022" and "Clang-cl 16" are nice to take the role of "preliminary C++23 compiler", or even, replace the 32-bit compiler "Microsoft Visual C++ 2017".

The MSC++2022 compiler has implemented the full features of C++20 so early, far away from other compilers. What's more, it has built-in Signed128 and a precompile-header "__msvc_all_public_headers.hpp" just like those GNU compilers did, and of course, bugfixes and performance optimizations. It also supports legacy C++17 mode.

Furthermore, upgrading MSC++ to the 2022 version will also benefit the compiler Clang-cl, which has the most stable support of C++20 and C++23 (see aforementioned support list). Currently, the clang-cl aka "Clang diagnostics" doesn't support any c++20 headers as the MSC++2017 lacks support for these headers, which makes it bearly usable.

By the way, the winlibs.com build also has a Mingw64-clang version, packed up with latest stable GCC build (13.2), and it would be great if this clang compiler and the clang-cl compiler are set side-by-side; In that case, one participant can freely choose which STL that clang compiler using:

  • The clang using msSTL (clang-cl) would have the latest C++23 STL and language support. However, aside from VLAs, clang-cl doesn't support extended float types like float128, and other GNU dialects.

  • The clang using libstdc++ (mingw64) would be compatible with codes written for those GNUC++ compilers, and in many cases, would have a better runtime performance.

Oh, thank you! Your answer solved my confusion.

I'm using this compiler after contests. Since MSVC seems to appear more often in projects, I expected to practice using this compiler as I may deal with it a lot in the future.

Auto comment: topic has been updated by tatianyi (previous revision, new revision, compare).