lainchan / λ

(untitled)

Switch · 2024-01-28 08:27
tl;dr: Why is C++ compilation still slow even though computers get faster all the time? I have been programming in C++ since approx. 2001. Back then I did not mind the slow compile times; computers were slow in general, I had lots of free time and programming was more exciting anyway. However, what has been bugging me since at least 2017 (and that is 7 years now), is that even though I am upgrading my PC regularly, C++ does not seem to compile any faster. I have been waiting one second for GCC to compile on file in 2017; this depends on the project of course, but what I mean is the "perceived average time". I have upgraded my PC 3 times then, and I still wait this time. Of course, C++ has evolved, compilers now have additional diagnostics going on, etc. But my expectation would have been that C++ nowadays runs instantly like python, but it seems that is not gonna happen soon; especially since Rust set a new high when it comes to compile times. Has anyone more information about this? I have looked online for an article or a talk discussing this, but did not find one.
⍕ · 2024-01-28 16:00
Impossible to determine your bottleneck without knowing details about your code and your system.
protected · 2024-01-29 03:02
Likely file io. You can observe any operation on lots of small files remaining slow.
Vasya Pupkin · 2024-01-29 06:00
I was investigating this a little bit some time ago and it surprised me that according to gcc's "-ftime-report" flag up to 50% of the time spent was on parsing. Then I tried running "gcc -E source.cpp | wc -l" on many of the project files (SerenityOS in this case) and on some compilation units there were 100K+ after the preprocessor. >>38207 It's not the biggest bottleneck, the kernel will cache a lot in memory, it doesn't sit around waiting for the disk to spin It takes a long time because after includes and template instantiation there is a lot of code for the compiler to go through. Simpler c++ projects compile pretty fast (see the Odin compiler) but a lot of codebases use the STL and all the shinny new features extensively making compilation take forever
Dr. X · 2024-01-29 14:33
>>38202 Just check out FreePascal, which can rebuild itself in a few minutes, but it hasn't optimizations available in modern C++ compilers. In order for C++ to still justify its complexity leading to optimal use of resources(RAM, CPU), C++ compilers are forced to perform incredible optimizations that take a very long time. In addition, templates and the absence of modules do not increase the speed of compiling.
Crash Override · 2024-01-30 03:05
The compilers aren't designed to be cache friendly. Frequent cache misses invalidate most of the advancements of hardware, access to ram is quite slow. Also the standard library keeps growing, and additional features have increased the size of the codebase - compounding the issue.
Morpheus · 2024-01-30 12:13
>>38214 That made me write a small C++ application without the STL and indeed it compiles as fast as C. So STL makes things slow and adding Boost makes it even worse, it seems.
Terzibashjian · 2024-01-30 14:31
>>38214 Why do templates take so long? "Copy-paste this code for every type that uses it" seems like it should be a fairly simple operation.
nobody · 2024-01-30 19:36
>>38202 as they add more features to the language and especially add stuff to the standard library, parsing everything takes way longer, you will suffer for every header you include
Lady Jessica · 2024-01-31 06:43
>>38219 The implementation needs to be available in every translation unit (modules still aren't ready) that it's used. So you're compiling the same code multiple times in multiple places. Also >>38220
Nobody special · 2024-03-14 18:42
>>38202 Everything about c++ is a joke, make a big project in C where you need to write your own functions instead of using libraries and you will realize >wait a second, to make this stuff applicable to any type they need to use the heap and void pointers and that is why everything is so ffuarking slow. >but i was talking about compilation the headers are fuarrrking ginormous and classes are highly abstracted (where abstraction == the ratio of lines in the high level lang to the lines in asm)
James K · 2024-03-14 19:19
>>38549 >wait a second, to make this stuff applicable to any type they need to use the heap and void pointers That's typically the approach in C, but C++ has templates. Templates are faster at runtime, but take longer to compile. >classes are highly abstracted Source? Most of the basic operations in C++ seem the same as those in C. I don't see a C++ function generating much more code than would be required for the C version of the same thing.
t · 2024-03-15 06:12
>>38219 In order for any code to appear, a template must be instantiated (notice that template instantiation has a different meaning here than class instantiations for example), i.e., the template arguments must be determined at compile time so that the compiler can generate an actual entity (function, class, variable, alias, ...) Now a template specialization allows the customization of a primary template for a given set of instructions, meaning that the specialization provides an alternative definition that can be used instead of the original one. From a compiler perspective, specialization (at least explicit ones) and instantiations mean the same thing except that instantiations are generated by compiler directly (following the primary template definition) whereas specializations are written by the developer himself who has the ability to provide an alternative definition of the primary template. There are two kinds of template specializations : explicit ones which introduce names, for example cpp template <typename T> struct A { static const bool value = false; }; template <> struct A<float> { static const bool value = true; }; [code] In the example above, we make an explicit specialization from the primary template struct A. If we call the template struct with float as the template type parameter, then the compiler must not generate a new instantiation and has to the existing specialization. We can think of specializations as a way to tell the compiler to customize the primary template's definition. Thus, [code]A<T>::value == true if T is float. Partial template specialization provides an alternative definition of the template that is used instead of the primary definition when the arguments match those given by a partial specialization. However, unlike explicit specializations, partial specializations do not introduce new names. Instead, when the primary template name is used, any reachable partial specializations of the primary template are considered. cpp template <typename T> struct B { static const bool value = false; }; template <typename T> struct B<const T> { static const bool value = true; }; In the example above, we defined a primary template definition with a type T and a static constant variable member "value" which is false by default. When the primary definition is used, i.e., when there's no existing template instantiation/explicit specializations, the partial specialization is considered. If T appears to be a constant type, then the compiler has to use the existing partial specialization that we have defined and instantiate it. Now, the standard library heavily uses templates along a technique named SFINAE (which stands for substitution failure is not an error), back then when C++ didn't have concepts nor the `constexpr` keyword, it was kind of the only alternative to have compile time constraint on types. The standard library provides a utility class enable_if which is defined like this : cpp template <bool B, typename T> struct enable_if {}; template <typename T> struct enable_if<true, T> { using type = T; }; They are two template definitions, one that contains nothing and the other other (partially specialized!) that contains a member alias to T. As said previously, when a template is used in a context that requires a template instantiation, it is necessary to determine whether the instantiation is to be generated using the primary template definition or using the partial specialization. This is done by pattern matching the given template arguments with the template argument list of the partial specialization. For instance cpp using type1 = enable_if<true, int>::type; using type2 = enable<false, float>::type; type1 is equal to int because the partial specialization is considered and used (because C is true). However [code2]type2[/code2] is raising a compiler error because there is no existing member alias named type in the primary template definition. The enable_if allows us to constrain the place-holder types to a certain set of category of types. For instance, in order to write a factorial function that only accepts arithmetic types, we can use enable_if to constrain the type cpp template <typename T> typename enable_if<is_arithmetic<T>::value, T>::type factorial(T t) { ... } C++20 has introduced concepts which allow us to put constraints on type more easily without relying on SFINAE cpp template <typename T> requires is_arithmetic<T>::value T factorial(T t) { ... } Notice however, that it is possible to evaluate expressions' validity without using requires clause by using the void_t utility alias cpp template <typename ...> using void_t = void; void_t is an alias to void as long as the types passed as template arguments are valid. We can then use void_t in addition to SFINAE to evaluate whether an expression is valid to constrain our types more effectively (having compile ad-hoc polymorphism sort of) For example: cpp struct X { using member_type = int; }; template <typename T, typename = void> inline constexpr bool has_member_type = false; template <typename T> inline constexpr bool has_member_type< T, void_t<typename T::member_type>> = true; In the example above, there is a default anonymous template parameter to void in the primary template definition. In the partial specialization, the second template parameter is only valid if and only if T::member_type is valid. As for any template partial specializations, it is only considered if the second template parameter appears to be valid. Otherwise, substitution failure occurs and the compiler uses the primary template definition. Again the standard library heavily uses these tricks to provide adequate constraints on generic types. It has been demonstrated that concepts are much more faster to compile than SFINAE but since they want to preserve backward compatibility with code that makes use of the SFINAE interface, they haven't converted all the template machinery to concepts yet.
word · 2024-03-15 09:08
>>38555 Use some sliding window compression with a large window and see all that duplicate machine code templates generate due te expansion. Bigger binary, more cache misses, slower code. Thanks, but I'll stick with C.
Agent Richard Gill · 2024-03-15 10:35
>>38557 All of this machinery happens at compile time, it doesn't increase the size of binary files. It is true that C is a much simpler language with better compilation times.
lekalo · 2024-03-15 12:19
I've noticed that c++ is pretty fast but is m coming from python and golang.
Zhora · 2024-03-15 18:43
>>38558 It does increase bin size. Template Intantiation yields code expansion and the compiler voodoo you rargo cultists believe exists simply doesn't. Check your objdump, you don't have to take my word for it. I'm done trying to convince plainly wrong compiler hype true believers. It's like Yuri Bezmenov said, A demoralized person can not accept new information even in the face of plain obvious fact they will not believe anything but their demoralized world view. Keep dreaming, maybe someday you'll understand how to read/write ASM decently, until then just put up with a slow C/C++ code slinger that even generates ASM text as part of its buildchain which has to be re-lexxed, uggh.
The Fin · 2024-03-15 19:05
>>38560 Instantiations of objects and functions from templates are inline which on Linux is implemented by means of weak symbols. Those take space in the binary, but if they appear in several translation units, they count only once. It can lead to SMALLER programs after linkage than if you reimplement the same small function in all translation units. If you use templates to implement stuff that's only for one translation unit, you're supposed to put it inside an anonymous namespace. Then it will not support external linkage (like with static objects and functions). Using assembly for any purpose other than cryptography and hardware interfacing is the ultimate freshman-having-a-massive-Dunning-Kruger-phase giveaway.
James K · 2024-03-16 14:01
>>38561 >weak symbols Incidentally, this is a pretty good explanation for C++ compiling like ass. Every file needs to recompile a whole bunch of code and then that work is just thrown away at the end. The ultimate reason for all of this is because C++ compilers are stuck with this weird shell like interface where they produce object files then those are combined into executables. I'm sure there could be a lot of performance improvements if the compiler were just invoked once on all source files, but it would be very hard to retrofit that onto the idea of compilation units. Of course the designers of C were not stupid. In a time where many users of the language would have had to write their own compilers, it made sense to do things like this. Many of the features that make it easy to write a C compiler have come back around to make it hard to write a fast C compiler. The preprocessor, for instance, makes it very easy way to share information between files using #include directives. "Copy the text from this file" is dead easy to implement, but in practice it means parsing the same bit of source code potentially hundreds of times. The world of computing has grown far beyond what C was designed for, and it is now questionable what utility it holds. Especially in the desktop space, I feel it has very little to offer besides the fact that so much stuff is already written in it.
Koichiro · 2024-03-16 17:49
>>38560 It is not uncommon to encounter an attitude that "if it’s elegant, flexible, high-level, general, readable, etc., it must be slow and increase binary size". This attitude is so ingrained that you end up rejecting essentially every C++ facility not offered by C without feeling the need for evidence. This is unfortunate because the low-level alternative involves more work at a lower level of abstraction, more errors, and more maintenance headaches. Bit, byte, pointer, and array fiddling should be the last resort rather than the first choice. C++ balances costs with benefits for so called "advanced features", such as classes, inheritance, templates, free store (heap), exceptions, and the standard library. If you need the functionality offered by these facilities, you can rarely (if ever) provide better hand-coded alternatives. Templates are a compile-time composition mechanism implying no runtime or space cost compared to equivalent hand-written code. Templates allow you to parameterize classes and functions with types and integers. If you like fancy words, they provide parametric polymorphism complementing the ad-hoc polymorphism offered by class hierarchies. Generally, systematic use of templates is called “generic programming” which complements the "object-oriented programming" that you get from systematic use of class hierarchies. >Template Intantiation yields code expansion and the compiler voodoo you rargo cultists believe exists simply doesn't. In sharp contrast to the claim that templates cause code bloat, it so happens that templates can be used to save code space. A C++ compiler is not allowed to generate code for an unused template function. This implies that if a program uses only 3 of a template class' member functions, only those three functions will occupy space in memory. The equivalent in non-template classes is not common and quite hard to achieve for virtual functions. The perfect inlining of small member functions and the guarantee that no code is generated for unused functions is the reason that function objects have become the preferred way of parametrizing algorithms. A function object is an object of a class with the application operator operator () defined to perform a required action. cpp template <class T> struct less { bool operator()(const T &a, const T &b) const { return a < b; } }; The function object less is used by most standard library facilities that need to perform a comparison. The result can be factors of improvement in runtime compared to parametrization with function pointers. The selection of types and operations is done at compile time and always lead to major improvements compared to hand-optimized C counterpart. Templates can also accept integer arguments, which means you can do arbitrary computations at compile time.
vector · 2024-03-16 20:15
>>38563 >Incidentally, this is a pretty good explanation for C++ compiling like ass. Every file needs to recompile a whole bunch of code and then that work is just thrown away at the end. Good thing modules are now a thing. :) >Of course the designers of C were not stupid. C has inline functions too which are compiled into weak symbols the exact same way as C++.
James K · 2024-03-16 21:33
>>38567 >modules are now a thing I'm not sure the degree to which they actually exist in practice. It will certainly be a while before they can be used, and quite difficult to properly integrate them into existing compilers. >Good thing Is it? I feel like they might as well have just scrapped the whole language and started over*, rather than adding another thing to the pile of complexity. >C has inline functions too which are compiled into weak symbols the exact same way as C++. I don't think that all design decisions throughout the history of C were good, just that its compilation model was originally justified and now is not. You could probably take the addition of inline functions to be a significant milestone in the transition between the justified and not-justified states. Note that C would be worse now if it didn't have inline functions and weak symbols to implement them. What happened was that its compilation model became outdated, and then these were added in response to that. *I can imagine people taking issue with this, so I think I should justify the idea somewhat. The primary issue with such a change would be integrating existing C code. If one were to generalise the concept of a header file, it could then be used as the standard interchange format into which existing headers can be converted and then subsequently imported into the new language. This would allow further creation of new languages speaking the common format. Opening the space of C-like languages up to free and easy competition seems immensely beneficial. The issue of generic types still rears its head, but in a much less pronounced way as these now only need to exist between dynamic libraries which was already quite difficult. On the far end of practicality, I would like to see a standard version of something akin to LLVM IR used for this new header format. Some kind of common portable assembly-like code which allows for things such as generic/inline functions to be included in the output header files. This would essentially give the new header files semantics somewhere between the existing C and C++ versions (from C, generic types are added; but from C++, OOP is removed). Ideally this is in a binary format that is easier to read and deal with. The new format would only need to be used at the boundaries of libraries rather than within projects, which is what allows compilers for the new language to work better.
Koichiro · 2024-03-17 07:43
The C compilation model never made sense, even at the time. It was a hack to reuse existing linkers & linked library formats, which didn't support embedded headers.
James K · 2024-03-17 08:22
>>38574 Reusing existing code makes sense.
x<->y · 2024-03-17 18:17
>>38574 Thinking about it further it doesn't make sense at all. They could have created a dummy library entry called "cheaders" that contains the C headers, even when reusing existing linkers the headers can be embedded in the library. #include duplicating files by default is also baffling
James K · 2024-03-17 19:42
>>38580 >#include duplicating files by default is also baffling Without this, header files wouldn't be able to inherit macros defined in the file that included them. As it currently stands, the contents of a file can change depending on how it's included: // main.c int main(int argc, char **argv); // a.c #include "main.c" // b.c #define main(...) x #include "main.c" int *y = &x; Beyond that, these changes would essentially cascade down and change how the whole process works. If the object files can interdepend, you might as well not even bother with headers. Which I would say is good now but maybe was not as good of an idea then. The requirements for a C compiler have changed over the decades, and this serves to obscure what motivated the decisions we live with today. >They could have created a dummy library entry called "cheaders" that contains the C headers Too cheesy.
Nell · 2024-03-17 20:05
>>38574 Yes, real languages have proper module systems. Precedence for this existed before the 1970s.
Spooky · 2024-03-17 20:21
>>38582 Using a file as if it were a macro by including it in multiple places with different #define arguments is an extreme outlier, even moreso than an #include inside a struct or function or initializer. It makes no sense to make the default favor this usage. These are not large changes, even merging header files and libraries is not large. The compiler would just need to get the headers out of libraries at the start of compilation, and merge duplicate struct definitions - reporting error if the struct definitions are not identical. Libraries that depend on other libraries can duplicate the struct definitions and have external symbols of functions & vars like they always have.
James K · 2024-03-18 06:11
>>38584 >multiple places with different #define arguments is an extreme outlier Yes, but you still want definitions from within an included file to be made present. You could still manage this with the compiled approach, but it involves the pre-processor being much more tightly coupled with the compiler (it needs to be able to output the definitions of symbols into the object files of the headers). My point generally is not that it's a good thing to do it this way, but that it is more complicated to compile the headers than it is to not compile the headers, and it probably wasn't as big of a concern when C was being designed.
Nemissa · 2024-03-18 19:01
My point is that statements like "C has bad design for historical reasons, it made sense at the time" is wrong. It wasn't for hardware limitations, copy pasting files with a preprocessor is expensive yet was the approach used. It wasn't for software limitations, better hacks could have been done. It was for organizational reasons, lack of better ideas, or thinking it was easier & quicker to do some things sloppily despite the amount of time it quickly cost. It's not just looking hindsight some decisions were just wrong and would clearly snowball into huge wastes of time and energy. People don't say "JavaScript is bad for historical reasons" they say Netscape rushed it. It's misleading people and worsening their understanding to say needless faults are from historical reasons. C doesn't need fake justifications either it's still around because other languages mess up far worse. >>38585 I just meant #include by default should have `#pragma once` / include guards applied to it and a separate keyword (e.g. #paste) copies the file as many times as it is asked. Or the other way around, an #import keyword that acts like `#pragma once` is there in the file. That would be way saner. Better for programming and faster for the compiler - don't even need to look at the file contents to see that this is a file that is only included once.
James K · 2024-03-19 05:27
>>38587 >some decisions were just wrong Perhaps, but I have to disagree on this case in particular. C was successful because it was easy to implement, and this kind of thing is the exact reason why. A version of C that did everything right would have been totally unsuccessful, and indeed many such languages existed and were unsuccessful. You can debate whether C did these things with a view to success, or simply stumbled onto them by accident, but I don't think that motivation is relevant to impact. >I just meant #include by default should have `#pragma once` / include guards I don't think this would speed up compilation by a huge amount. AFAIK the bigger issue is parsing the files that are included rather than skipping the files that aren't. A lot of projects use #pragma once and I'm not sure if it massively improves their compilation times.
Mentat · 2024-03-19 15:00
>>38589 >Perhaps, but I have to disagree on this case in particular. C was successful because it was easy to implement, and this kind of thing is the exact reason why. Forth is easier to implement. The C language was successful solely because of UNIX. >I don't think this would speed up compilation by a huge amount. Isn't this the main reason C++ language compilation times are so bad, because it explodes the number of files which must be compiled?
James K · 2024-03-19 19:02
>>38590 >because it explodes the number of files which must be compiled These are two similar issues, specifically duplicate headers in the same compilation unit vs across compilation units. When in the same unit, duplicate headers are removed during pre-processing, which means they won't actually be compiled. While reading all these files multiple times likely isn't fast, it also probably isn't that bad (it's only even a problem if large header files are included directly many times, and even then the OS caching probably saves you a lot of time). The bigger issue is the across compilation units case. It requires that all headers are fully compiled across all compilation units, and with templates this also means the implementation of every template function must be compiled multiple times as well. This is the main source of slowdown as far as I'm aware. >The C language was successful solely because of UNIX. I'm almost certain that, if UNIX used Forth, we would not all be currently using Forth for everything (or UNIX for that matter). The two things each helped the other to become popular. A version of C that was more complicated would almost certainly not have caught on in the same way.
Unidentified · 2024-04-06 09:25
>>38590 >>38595 Forth has the same problem as Lisp. When a language is too open to expansion, you end up designing an application-specific pseudo-DSL that needs to be learned before anyone but the guy who programmed it can begin to read it. Don't get me wrong, C is a deeply flawed language. But it benefits a lot from being small and staying small.
Naomi Nascimento · 2024-04-06 15:39
A few reasons. The size of standard library includes has exploded. <algorithm> in C++20 pulls in half a _million_ lines of code on some systems. In theory modules help with this. In theory. The complexity of the language has exploded. A surprising amount of modern optimization is a bunch of "is there some weird quirky edge case where this optimization might not be valid" checks, which keep having to get more and more elaborate due to e.g. C++11 memory model spooky-action-at-a-distance. Modern compilers chase more and more and more long-tail questionably-worth-it optimizations, which _drastically_ slows down compilation. Modern compilers have more and more internal structure instead of being monoliths, which helps a bunch of things but hurts compilation times, sometimes drastically. Clang runs some optimization passes twice rather than add a special case in an intermediate pass, for instance. Much cleaner code... and much slower. Single-threaded performance hit a knee with the death of Dennard scaling. (And charts that show a theoretical continued increase in single-threaded performance tend to be lying. The gains the past while are mainly due to compilers applying more auto-vectorization and auto-parallelization - both of which take more compiler time, and neither of which are particularly applicable to a compiler's code.)
James K · 2024-04-06 16:17
>>38722 I mean the greater issue with Forth is that it's stinky garbage for people who never found out about Smalltalk. It's essentially all of the worst vibes of CL distilled into one language. >When a language is too open to expansion, you end up designing an application-specific pseudo-DSL that needs to be learned before anyone but the guy who programmed it can begin to read it. I don't think the problem is as you describe it. Macros are used rarely in well-written lisp code, and essentially not at all in Scheme. All programming languages that offer a means of abstraction by binding names to procedures essentially offer a method for creating a new language to solve a problem, and reading code is the process of learning that language. The only difference in lisp is that the language is more explicit and more expressive. Consider for instance, "with"-blocks. (with-open-file (stream "file.txt" :direction :output) (format stream "text") (terpri stream)) The with-block does the job of both opening and closing the file. The relationship between open and close is explicitly a part of the code, whereas in the C-like equivalent, one must infer that each open has a corresponding close. For files, this is obvious, but it may be genuinely illuminating for less well-known examples. What I think most people who make this "unreadable macro language" argument omit, is that one can usually determine what a macro does by reading its name. Indeed it it is surprising how readily one can infer the meaning of lisp code even divorced from the context it was written in. Once you have learned a few programming languages, you can generally read code from languages you don't know, even if writing it would be difficult. The same holds for lisp.
quote · 2024-04-06 16:56
>>38730 Forth is spectacular on small Harvard-architecture microcontrollers. People tend to forget that. Forth is abysmal on giant superscalar OOO processors. People tend to forget that, too.
renames · 2024-04-08 18:29
>>38729 This chart made me think... Moores law is not an exponential growth line like he was selling to investors, it's a sigmoid curve! And the same for AI right now too! Processor growth was huge when it started and kept getting bigger but now we've hit a plateau. ML growth was getting faster and faster and - while people are finding lots of new uses for it - the technology behind LLM's hasn't advanced much at all and we're starting to see that plateau too! It seems like the age when computer science was new is coming to an end as the technologies begin to plateau and we run out of new ideas, just reiterating on ones that were already made. Part of me feels a bit sad about that, another part feels optimistic that this is one of MANY pleateaus and we still have a long way up to go, another voice of optimism says the journey of growth and discovery will never truly end, and other voice is optimistic that this is our time to really refine the technologies we were given and start making breakthroughs in entirely novel spaces yet unexplored! What do lainons think?
Agent Jones · 2024-04-08 19:27
>>38758 Moore's law was just about transistor density. Everyone always knew there were going to be physical limits, you can't make a subatomic transistor. Performance is a different thing entirely. In Moore's day you got performance by increasing the clock speed, which is directly correlated with transistor density. These days you mainly get performance improvement by changing the microarchitecture. This is much more of an engineering thing than a physics thing. Adding parallelism and fast interconnects also helps some workloads but not usually compilers, which is relevant to this thread. Luckily with compilers you can almost always just do make -j16 and it works great. Same with ML, the reason ML exploded was because it turned out throwing tons of compute at problems actually worked. Then the limits of that were reached because compute isn't free, and now a lot of ML research is focused on making models smaller and more efficient, which means understanding how they work, which it turns out is quite different from just making them work. Additionally nowadays you are getting machines designed that are specifically made to speed up machine learning tasks (aka, doing lots of int8 dot products in parallel). The general trend of adding more and more silicon or even building entire specialized machines to take care of specialized problem areas will probably continue. >It seems like the age when computer science was new is coming to an end as the technologies begin to plateau and we run out of new ideas, just reiterating on ones that were already made. There's always tons of new ideas to be had. Take a look at mathematics, thousands of years old (even 'modern math' is at least 130 years old) and flourishing today like almost never before. It's just that the low-hanging fruit has mostly been picked and the people getting into the field now have to work harder to do anything interesting.
the Mailman · 2024-04-09 10:02
>>38758 Almost everything that people breathlessly predict as exponential curves are really sigmoids. You're absolutely correct. The annoying thing is that it's virtually impossible to predict where a sigmoid will top out until you're already most of the way through. (Some things are breathlessly predicted as exponential decays towards zero instead, like process node sizes. Those typically are really exponential decays towards a positive constant instead.) >>38759 > Luckily with compilers you can almost always just do make -j16 and it works great. Not if you want good LTO, which is one of the major drivers of modern compiled performance headlines... most attempts at multithreading LTO come at the expense of performance of the compiled program.