Despite the fact that my algorithms course was ostensibly about learning how to come up with efficient solutions to various problems, the two courses I took that have helped me the most with writing performant code in my career were my compilers course and my architecture course. The compilers course gave me a much stronger understanding of what actually happens when running a line of code I wrote and helped me understand better what types of optimizations could potentially be performed based on the way I write an algorithm, and the architecture course taught me about how a modern CPU actually works with regards to caching, out-of-order processing, branch prediction, etc.
On the other hand, the types of things we discussed in my algorithms course felt very hit-or-miss with regards to whether they actually felt useful or not. I'm not just talking about high-level abstractions that can miss important details in the real world like "memory can be accessed in constant time" either, but solving problems that were so contrived to the point of being almost implausible. The example I always remember is that in one of our problems sets, we were asked to write an algorithm that sorted an array of size N with each element within K indices of the correct sorted position in O(n*log(k)) time. I can't think of any situation where I'd have data so large with a small enough strict upper bound on K that such an algorithm would be necessary, but even if I did find myself in that situation, that's the exact type of input that the naive quicksort implementation would perform more efficiently on!
Maybe someday we'll have powerful enough tools that we can generate code that's performant without needing to do it ourselves, but at least for now, writing code that a computer executes efficiently is much easier when you actually understand what's being run on the computer and how it runs it, and a compilers course is a great way to start learning about the first half of that.
> Despite the fact that my algorithms course was ostensibly about learning how to come up with efficient solutions to various problems
The usual advanced undergraduate / graduate level algorithms class is not supposed to teach you that. It's an introductory class to various techniques used in algorithm design and analysis, beyond those included in the undergraduate algorithms and data structures class.
Core algorithms classes then assume familiarity with those techniques. One of those core classes may be algorithm engineering, if your CS department has someone interested in the topic. And if the department assumes that there are enough students interested in it – the overlap between people interested in algorithms and software is often surprisingly small.
> It's an introductory class to various techniques used in algorithm design and analysis
I feel like you're being a bit too pedantic here, because I don't really see how "learning various techniques used in algorithm design and analysis" doesn't somehow fall under the umbrella of "learning how to come up with efficient solutions to various problems"; an algorithm is certainly a solution to a certain type of problem, and efficiency is certainly a property that would be investigated as part of "algorithm analysis". Every single problem on our numerous homework sets and every question on every exam we had required us to design and then analyze our own algorithm for solving a problem presented to us, so it seems kind of silly to claim that we weren't supposed to be learning how to solve those problems, given that it's literally what they graded us on.
My best guess is that you objected to my characterization because you read it as a "why" rather than a "what". Whether the course was intended to teach us real-world skills or just try to teach the prerequisites needed for a career in algorithmic research doesn't really change the point I was trying to make, which was a potential answer to the question posed by the article, "Why take a compiler course?".
The introductory algorithms class is much like introductory programming: it teaches you the basic tools, but it's not very practical on its own. If you are not interested in studying algorithms further, the class may be interesting and educational but probably not very useful.
Some CS departments make the matter worse by calling the class Advanced Algorithms, which gives students a wrong impression. Students may believe that they are going to learn algorithms instead of tools for working with algorithms. I prefer the approach our mathematics department had when I was a student: they gave classes at the same level names like "Elements of Set Theory" and "Introduction to Elementary Number Theory".
Additionally, the example you used was actually pretty good. There is a parameter k that determines how easy or hard the specific instance is. The class used sorting as an example, because it's a non-trivial problem with many algorithms students are already familiar with. And the optimization target was asymptotic complexity, because it's easy to deal with without turning the assignment into a semester-long project.
If your job is designing practical algorithms (as mine is), you'll often end up in similar situations. Maybe you get the parameter k as a guarantee that allows you to use an algorithm that is faster with easy instances than the general-purpose algorithm. Or maybe you design an algorithm with its resource usage depending on k, regardless of the value. Or maybe the algorithm you already have is often faster than expected, and you want to find the parameters that determine how easy or hard an instance is. Or maybe you already have the algorithm and know the parameters, and you want to determine and log the values of the parameters in case a user reports worse than expected performance in some situations.
On the other hand, the types of things we discussed in my algorithms course felt very hit-or-miss with regards to whether they actually felt useful or not. I'm not just talking about high-level abstractions that can miss important details in the real world like "memory can be accessed in constant time" either, but solving problems that were so contrived to the point of being almost implausible. The example I always remember is that in one of our problems sets, we were asked to write an algorithm that sorted an array of size N with each element within K indices of the correct sorted position in O(n*log(k)) time. I can't think of any situation where I'd have data so large with a small enough strict upper bound on K that such an algorithm would be necessary, but even if I did find myself in that situation, that's the exact type of input that the naive quicksort implementation would perform more efficiently on!
Maybe someday we'll have powerful enough tools that we can generate code that's performant without needing to do it ourselves, but at least for now, writing code that a computer executes efficiently is much easier when you actually understand what's being run on the computer and how it runs it, and a compilers course is a great way to start learning about the first half of that.