什么时候组装速度比 c 快?

One of the stated reasons for knowing assembler is that, on occasion, it can be employed to write code that will be more performant than writing that code in a higher-level language, C in particular. However, I've also heard it stated many times that although that's not entirely false, the cases where assembler can actually be used to generate more performant code are both extremely rare and require expert knowledge of and experience with assembly.

This question doesn't even get into the fact that assembler instructions will be machine-specific and non-portable, or any of the other aspects of assembler. There are plenty of good reasons for knowing assembly besides this one, of course, but this is meant to be a specific question soliciting examples and data, not an extended discourse on assembler versus higher-level languages.

Can anyone provide some specific examples of cases where assembly will be faster than well-written C code using a modern compiler, and can you support that claim with profiling evidence? I am pretty confident these cases exist, but I really want to know exactly how esoteric these cases are, since it seems to be a point of some contention.

转载于:https://stackoverflow.com/questions/577554/when-is-assembly-faster-than-c

weixin_41568134
MAO-EYE Unless your brain has a -O3 flag, you're probably better off leaving optimisation to the C compiler :-)
接近 2 年之前 回复
csdnceshi50
三生石@ Earlier in my career, I was writing a lot of C and mainframe assembler at a software company. One of my peers was what I'd call an "assembler purist" (everything had to be assembler), so I bet him I could write a given routine that ran faster in C than what he could write in assembler. I won. But to top it off, after I won, I told him I wanted a second bet - that I could write something faster in assembler than the C program that beat him on the prior wager. I won that too, proving that most of it comes down to the skill and ability of the programmer more than anythings else.
大约 3 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 For an esoteric example, do a web search for pclmulqdq crc. pclmulqdq is a special assembly instruction. The optimized examples use about 500 lines of assembly code. Some X86 also have a crc32c instruction for a specific case of crc32. Benchmark results to generate crc32 over 256MB (256*1024*1024) byte array: c code using table => 0.516749 sec, assembly using pcmuldq => 0.0783919 sec, c code using crc32 intrinsic => 0.0541801 sec.
3 年多之前 回复
csdnceshi54
hurriedly% It's not even always the case that you need to rewrite something in assembly to reap the benefits of knowing assembly. Simply recompiling your C algorithm in various forms and observing the assembly that the compiler generates will allow you to write more efficient code in C.
3 年多之前 回复
weixin_41568127
?yb? I strongly disagree that answers to this question need to be "opinion based" - they can quite objective - it is not something like trying to compare performance of favorite pet languages, for which each will have strong points and draw backs. This is a matter of understanding how far compilers can take us, and from which point it is better to take over.
5 年多之前 回复
csdnceshi68
local-host All the greatest questions have 256 votes.
5 年多之前 回复
csdnceshi59
ℙℕℤℝ Actually, the short answer is: Assembler is always faster or equal to the speed of C. The reason is that you can have assembly without C, but you can't have C without assembly (in the binary form, which we in the old days called "machine code"). That said, the long answer is: C Compilers are pretty good at optimizing and "thinking" about things you don't usually think of, so it really depends on your skills, but normally you can always beat the C compiler; it's still only a software that can't think and get ideas. You can also write portable assembler if you use macros and you're patient.
接近 6 年之前 回复
weixin_41568131
10.24 actually it is quite trivial to improve upon compiled code. Anyone with a solid knowledge of assembly language and C can see this by examining the code generated. Any easy one is the first performance cliff you fall off of when you run out of disposable registers in the compiled version. On average the compiler will do far better than a human for a large project, but it is not hard in a decent sized project to find performance issues in the compiled code.
接近 6 年之前 回复
weixin_41568183
零零乙 Unfortunately questions like this would be closed for being too broad, or opinionated in 5 seconds these days.
6 年多之前 回复
csdnceshi67
bug^君 As someone just begining to learn asm, I find the responses to this question very useful.
大约 7 年之前 回复
csdnceshi65
larry*wei One of the greatest questions I've seen. Thank you Adam!
接近 8 年之前 回复
csdnceshi56
lrony* And now an other question would be appropriate: When does the fact that assembler is faster than C actually matters?
大约 11 年之前 回复

28个回答

Here is a real world example: Fixed point multiplies on old compilers.

These don't only come handy on devices without floating point, they shine when it comes to precision as they give you 32 bits of precision with a predictable error (float only has 23 bit and it's harder to predict precision loss). i.e. uniform absolute precision over the entire range, instead of close-to-uniform relative precision (float).


Modern compilers optimize this fixed-point example nicely, so for more modern examples that still need compiler-specific code, see


C doesn't have a full-multiplication operator (2N-bit result from N-bit inputs). The usual way to express it in C is to cast the inputs to the wider type and hope the compiler recognizes that the upper bits of the inputs aren't interesting:

// on a 32-bit machine, int can hold 32-bit fixed-point integers.
int inline FixedPointMul (int a, int b)
{
  long long a_long = a; // cast to 64 bit.

  long long product = a_long * b; // perform multiplication

  return (int) (product >> 16);  // shift by the fixed point bias
}

The problem with this code is that we do something that can't be directly expressed in the C-language. We want to multiply two 32 bit numbers and get a 64 bit result of which we return the middle 32 bit. However, in C this multiply does not exist. All you can do is to promote the integers to 64 bit and do a 64*64 = 64 multiply.

x86 (and ARM, MIPS and others) can however do the multiply in a single instruction. Some compilers used to ignore this fact and generate code that calls a runtime library function to do the multiply. The shift by 16 is also often done by a library routine (also the x86 can do such shifts).

So we're left with one or two library calls just for a multiply. This has serious consequences. Not only is the shift slower, registers must be preserved across the function calls and it does not help inlining and code-unrolling either.

If you rewrite the same code in (inline) assembler you can gain a significant speed boost.

In addition to this: using ASM is not the best way to solve the problem. Most compilers allow you to use some assembler instructions in intrinsic form if you can't express them in C. The VS.NET2008 compiler for example exposes the 32*32=64 bit mul as __emul and the 64 bit shift as __ll_rshift.

Using intrinsics you can rewrite the function in a way that the C-compiler has a chance to understand what's going on. This allows the code to be inlined, register allocated, common subexpression elimination and constant propagation can be done as well. You'll get a huge performance improvement over the hand-written assembler code that way.

For reference: The end-result for the fixed-point mul for the VS.NET compiler is:

int inline FixedPointMul (int a, int b)
{
    return (int) __ll_rshift(__emul(a,b),16);
}

The performance difference of fixed point divides is even bigger. I had improvements up to factor 10 for division heavy fixed point code by writing a couple of asm-lines.


Using Visual C++ 2013 gives the same assembly code for both ways.

gcc4.1 from 2007 also optimizes the pure C version nicely. (The Godbolt compiler explorer doesn't have any earlier versions of gcc installed, but presumably even older GCC versions could do this without intrinsics.)

See source + asm for x86 (32-bit) and ARM on the Godbolt compiler explorer. (Unfortunately it doesn't have any compilers old enough to produce bad code from the simple pure C version.)


Modern CPUs can do things C doesn't have operators for at all, like popcnt or bit-scan to find the first or last set bit. (POSIX has a ffs() function, but its semantics don't match x86 bsf / bsr. See https://en.wikipedia.org/wiki/Find_first_set).

Some compilers can sometimes recognize a loop that counts the number of set bits in an integer and compile it to a popcnt instruction (if enabled at compile time), but it's much more reliable to use __builtin_popcnt in GNU C, or on x86 if you're only targeting hardware with SSE4.2: _mm_popcnt_u32 from <immintrin.h>.

Or in C++, assign to a std::bitset<32> and use .count(). (This is a case where the language has found a way to portably expose an optimized implementation of popcount through the standard library, in a way that will always compile to something correct, and can take advantage of whatever the target supports.) See also https://en.wikipedia.org/wiki/Hamming_weight#Language_support.

Similarly, ntohl can compile to bswap (x86 32-bit byte swap for endian conversion) on some C implementations that have it.


Another major area for intrinsics or hand-written asm is manual vectorization with SIMD instructions. Compilers are not bad with simple loops like dst[i] += src[i] * 10.0;, but often do badly or don't auto-vectorize at all when things get more complicated. For example, you're unlikely to get anything like How to implement atoi using SIMD? generated automatically by the compiler from scalar code.

weixin_41568134
MAO-EYE To be fair, this is example is a poor one, at least today. C compilers have long been able to do a 32x32 -> 64 multiply even if the language doesn't offer it directly: they recognize that when you cast 32-bit arguments to 64-bit and then multiply them, it doesn't need to do a full 64-bit multiply, but that a 32x32 -> 64 will do just fine. I checked and all of clang, gcc and MSVC in their current version get this right. This isn't new - I remember looking at compiler output and noticing this a decade a ago.
大约 2 年之前 回复
csdnceshi68
local-host Amazing answer. I had to look up several (3), in depth things discussed here that i didn't know, in order to understand it. This is probably because i don't know much about how compilers work yet. But i will soon. : )
3 年多之前 回复
csdnceshi55
~Onlooker the point of the answer is to show that writing optimized assembly code by hand is not even always the best answer, because the compiler does not know the intention of your code. The intrinsic lets the compiler know what you intend to do, and it allows it to even further optimize it through various features. Usually such intrinsics translate to relatively simple assembler code, but they carry extra information that the compiler can use in its optimization phase. Plus, if the target platform does not support it, the compiler can provide a compatible alternative.
接近 5 年之前 回复
weixin_41568184
叼花硬汉 Note that at least with regard to register allocation flexibility, one should use an "extended inline assembly" rather than simple asm() calls. This way, the compiler is able to allocate registers in build time.
大约 5 年之前 回复
csdnceshi54
hurriedly% originally you was showing us a case when asm is more efficient than C. But what is you finished with? __ll_rshift is a C construct! Compiler specific although, but not asm.
接近 6 年之前 回复
csdnceshi65
larry*wei Actually, the code here is quite readable: the inline code does one unique operation, which is immediately understable reading the method signature. The code lost only slowly in readibility when an obscure instruction is used. What matters here is we have a method which does only one clearly identifiable operation, and that's really the best way to produce readable code these atomic functions. By the way, this is not so obscure a small comment like /* (a * b) >> 16 */ can't immediately explain it.
6 年多之前 回复
csdnceshi61
derek5. The "right" solution would be for the language to provide a way of requesting what one wants to do. Writing code whose naive interpretation would be horribly inefficient in the hope that the compiler will perform a particular optimization is a good way to get burned when switching compiler versions. This can be especially true in cases where one knows things about the sizes of operands that the compiler does not (for example, what compilers could optimize uint_quotient=ulong_dividend/uint_divisor in the case where ulong_dividend is known to be less than 2^32 times uint_divisor?)
6 年多之前 回复
csdnceshi53
Lotus@ also for these one liners, it doesn't hurt to use an #if #else pre-processor statement.
接近 7 年之前 回复
csdnceshi62
csdnceshi62 Hi Slacker, I think you've never had to work on time-critical code before... inline assembly can make a *huge difference. Also for the compiler an intrinsic is the same as normal arithmetic in C. That's the point in intrinsics. They let you use a architecture feature without having to deal with the drawbacks.
大约 10 年之前 回复
csdnceshi80
胖鸭 Actually, a good compiler would produce the optimal code from the first function. Obscuring the source code with intrinsics or inline assembly with absolutely no benefit is not the best thing to do.
大约 10 年之前 回复
weixin_41568131
10.24 How about things like {x=c%d; y=c/d;}, are compilers clever enough to make that a single div or idiv?
大约 10 年之前 回复
csdnceshi69
YaoRaoLov I've long known about this one.
大约 11 年之前 回复

Many years ago I was teaching someone to program in C. The exercise was to rotate a graphic through 90 degrees. He came back with a solution that took several minutes to complete, mainly because he was using multiplies and divides etc.

I showed him how to recast the problem using bit shifts, and the time to process came down to about 30 seconds on the non-optimizing compiler he had.

I had just got an optimizing compiler and the same code rotated the graphic in < 5 seconds. I looked at the assembly code that the compiler was generating, and from what I saw decided there and then that my days of writing assembler were over.

csdnceshi59
ℙℕℤℝ I really can't think of any platform where a compiler would be likely to get within a factor or two of optimal code for an 8x8 rotate.
2 年多之前 回复
csdnceshi59
ℙℕℤℝ On what processor? On 8086, I'd expect that optimal code for an 8x8 rotate would load DI with 16 bits of data using SI, repeat add di,di / adc al,al / add di,di / adc ah,ah etc. for all eight 8-bit registers, then do all 8 registers again, and then repeat the whole procedure three more times, and finally save four words in ax/bx/cx/dx. No way an assembler is going to come close to that.
2 年多之前 回复
weixin_41568174
from.. Did the optimizing compiler compile the original program or your version?
5 年多之前 回复
csdnceshi67
bug^君 He may have seen a code he couldn't write :/
大约 6 年之前 回复
csdnceshi80
胖鸭 Yes it was a one bit monochrome system, specifically it was the monochrome image blocks on an Atari ST.
11 年多之前 回复
csdnceshi72
谁还没个明天 Just wondering: Was the graphic in 1 bit per pixel format?
11 年多之前 回复

You don't actually know whether your well-written C code is really fast if you haven't looked at the disassembly of what compiler produces. Many times you look at it and see that "well-written" was subjective.

So it's not necessary to write in assembler to get fastest code ever, but it's certainly worth to know assembler for the very same reason.

csdnceshi69
YaoRaoLov In my experience compiler output is well, random. Sometimes it's really good and optimal and sometimes is "how could this garbage have been emitted".
2 年多之前 回复
weixin_41568134
MAO-EYE "So it's not necessary to write in assembler to get fastest code ever" Well, I've not seen a compiler do the optimal thing in any case that was not trivial. An experienced human can do better than the compiler in virtually all cases. So, it's absolutely necessary to write in assembler to get "the fastest code ever".
2 年多之前 回复

I think the general case when assembler is faster is when a smart assembly programmer looks at the compiler's output and says "this is a critical path for performance and I can write this to be more efficient" and then that person tweaks that assembler or rewrites it from scratch.

The simple answer... One who knows assembly well (aka has the reference beside him, and is taking advantage of every little processor cache and pipeline feature etc) is guaranteed to be capable of producing much faster code than any compiler.

However the difference these days just doesn't matter in the typical application.

csdnceshi61
derek5. This. Precisely. The compiler to beat the domain experts has not been invented yet.
2 年多之前 回复
csdnceshi75
衫裤跑路 I agree. Sometimes you use macros and scripts to generate assembly code in order to save time and develop rapidly. Most assemblers these days have macros; if not, you can make a (simple) macro pre-processor using a (fairly simple RegEx) Perl script.
接近 6 年之前 回复
csdnceshi77
狐狸.fox You forgot to say "given a lot of time and effort", and "creating a maintenance nightmare". A colleague of mine was working on optimising a performance-critical section of OS code, and he worked in C much more than assembly, as it let him investigate the performance impact of high-level changes within a reasonable timeframe.
大约 10 年之前 回复

Pretty much anytime the compiler sees floating point code, a hand written version will be quicker. The primary reason is that the compiler can't perform any robust optimisations. See this article from MSDN for a discussion on the subject. Here's an example where the assembly version is twice the speed as the C version (compiled with VS2K5):

#include "stdafx.h"
#include <windows.h>

float KahanSum
(
  const float *data,
  int n
)
{
   float
     sum = 0.0f,
     C = 0.0f,
     Y,
     T;

   for (int i = 0 ; i < n ; ++i)
   {
      Y = *data++ - C;
      T = sum + Y;
      C = T - sum - Y;
      sum = T;
   }

   return sum;
}

float AsmSum
(
  const float *data,
  int n
)
{
  float
    result = 0.0f;

  _asm
  {
    mov esi,data
    mov ecx,n
    fldz
    fldz
l1:
    fsubr [esi]
    add esi,4
    fld st(0)
    fadd st(0),st(2)
    fld st(0)
    fsub st(0),st(3)
    fsub st(0),st(2)
    fstp st(2)
    fstp st(2)
    loop l1
    fstp result
    fstp result
  }

  return result;
}

int main (int, char **)
{
  int
    count = 1000000;

  float
    *source = new float [count];

  for (int i = 0 ; i < count ; ++i)
  {
    source [i] = static_cast <float> (rand ()) / static_cast <float> (RAND_MAX);
  }

  LARGE_INTEGER
    start,
    mid,
    end;

  float
    sum1 = 0.0f,
    sum2 = 0.0f;

  QueryPerformanceCounter (&start);

  sum1 = KahanSum (source, count);

  QueryPerformanceCounter (&mid);

  sum2 = AsmSum (source, count);

  QueryPerformanceCounter (&end);

  cout << "  C code: " << sum1 << " in " << (mid.QuadPart - start.QuadPart) << endl;
  cout << "asm code: " << sum2 << " in " << (end.QuadPart - mid.QuadPart) << endl;

  return 0;
}

And some numbers from my PC running a default release build*:

  C code: 500137 in 103884668
asm code: 500137 in 52129147

Out of interest, I swapped the loop with a dec/jnz and it made no difference to the timings - sometimes quicker, sometimes slower. I guess the memory limited aspect dwarves other optimisations.

Whoops, I was running a slightly different version of the code and it outputted the numbers the wrong way round (i.e. C was faster!). Fixed and updated the results.

weixin_41568134
MAO-EYE FP add is commutative (a+b == b+a), but not associative (reordering of operations, so rounding of intermediates is different). re: this code: I don't think uncommented x87 and a loop instruction are a very awesome demonstration of fast asm. loop is apparently not actually a bottleneck because of FP latency. I'm not sure if he's pipelining FP operations or not; x87 is hard for humans to read. Two fstp results insns at the end is clearly not optimal. Popping the extra result from the stack would be better done with a non-store. Like fstp st(0) IIRC.
4 年多之前 回复
csdnceshi56
lrony* You mean associative? Or are there really cases when operations on reals are commutative but floating points are not?
接近 5 年之前 回复
weixin_41568196
撒拉嘿哟木头 Did you try SSE math? Performance was one of the reasons MS abandoned x87 completely in x86_64 and 80-bit long double in x86
6 年多之前 回复
weixin_41568131
10.24 Yeah, floats are not commutative, the compiler must do EXACTLY what you wrote, basically what @DavidStone said.
6 年多之前 回复
csdnceshi76
斗士狗 Or in GCC, you can untie the compiler's hands on floating point optimization (as long as you promise not to do anything with infinities or NaNs) by using the flag -ffast-math. They have an optimization level, -Ofast that is currently equivalent to -O3 -ffast-math, but in the future may include more optimizations that can lead to incorrect code generation in corner cases (such as code that relies on IEEE NaNs).
接近 8 年之前 回复
csdnceshi77
狐狸.fox nice one, using the vs compiler I got similar result (asm is faster). When using the /fp:fast as mentionned in the MSDN article then the C version goes faster.
大约 10 年之前 回复
csdnceshi50
三生石@ I used to do a bit of FPU assembly back in the day, but currently on x86 if you need to do hand optimised FPU assembly you should be doing it with the expanded instruction sets like SSE etc. As you won't gain much in real world performance using the FPU.
11 年多之前 回复
csdnceshi64
游.程 True - if you're memory bound not much can be done.
11 年多之前 回复
csdnceshi64
游.程 FYI: The code could even be faster if you replace the loop with sub ecx, 1 / bnz l1. Loop is a lot slower than it could be (for a reason, but that's another topic).
11 年多之前 回复
csdnceshi80
胖鸭 +1 for actually doing the profiling, but it'd be nice for you to include the output in your answer.
11 年多之前 回复

Matrix operations using SIMD instructions is probably faster than compiler generated code.

csdnceshi55
~Onlooker Not to mention that it can also be hard to write vectorizable C code. Because vectorizable C code looks exactly the same as non-vectorizable C code and if you make a mistake the compiler will just fall back to not vectorizing it. Or the next programmer who doesn't know about auto-vectorization will tweak something seemingly inconsequential and suddenly it's 3 times slower.
2 年多之前 回复
csdnceshi73
喵-见缝插针 Here is much ground for improvement. Visual Studio applied SSE only in scalar mode, which ofc wouldn't gain anything. social.msdn.microsoft.com/Forums/vstudio/en-US/…. Recent version support automatic vectorization. Not sure though the applicability since I read somewhere that many optimizations are prohibited due to all kind of boundary cases in C++ (especially in the area of exception handling).
3 年多之前 回复
csdnceshi76
斗士狗 You should use intrinsics for that, so it's not really assembler..
9 年多之前 回复
csdnceshi64
游.程 Mehrdad is right, though. Getting SSE right is quite hard for the compiler and even in obvious (for humans, that is) situations most compilers don't employ it.
11 年多之前 回复
weixin_41568110
七度&光 Sure you would, but the question did not ask where should I use assembly instead of C. It said when C compiler doesn't generate a better code. I assumed a C source that is not using direct SSE calls or inline assembly.
11 年多之前 回复
csdnceshi69
YaoRaoLov For many of those situations you can use SSE intrisics instead of assembly. This will make your code more portable (gcc visual c++, 64bit, 32bit etc) and you don't have to do register allocation.
11 年多之前 回复
weixin_41568110
七度&光 Yeah, modern compilers are pretty aware of SIMD instructions, getting the most out of it requires high level understanding of the algorithm used. Compilers generate SIMD for obvious cases only. Most of them don't take your whole algorithm and transform it to a parallel equivalent.
11 年多之前 回复
csdnceshi56
lrony* Compilers create SSE aware code, so that argument is not true
11 年多之前 回复
csdnceshi80
胖鸭 Some compilers (the VectorC, if I remember correctly) generate SIMD code, so even that is probably no longer an argument for using assembly code.
11 年多之前 回复

One of the posibilities to the CP/M-86 version of PolyPascal (sibling to Turbo Pascal) was to replace the "use-bios-to-output-characters-to-the-screen" facility with a machine language routine which in essense was given the x, and y, and the string to put there.

This allowed to update the screen much, much faster than before!

There was room in the binary to embed machine code (a few hundred bytes) and there was other stuff there too, so it was essential to squeeze as much as possible.

It turnes out that since the screen was 80x25 both coordinates could fit in a byte each, so both could fit in a two-byte word. This allowed to do the calculations needed in fewer bytes since a single add could manipulate both values simultaneously.

To my knowledge there is no C compilers which can merge multiple values in a register, do SIMD instructions on them and split them out again later (and I don't think the machine instructions will be shorter anyway).

I have read all the answers (more than 30) and didn't find a simple reason: assembler is faster than C if you have read and practiced the Intel® 64 and IA-32 Architectures Optimization Reference Manual, so the reason why assembly may be slower is that people who write such slower assembly didn't read the Optimization Manual.

In the good old days of Intel 80286, each instruction was executed at a fixed count of CPU cycles, but since Pentium Pro, released in 1995, Intel processors became superscalar, utilizing Complex Pipelining: Out-of-Order Execution & Register Renaming. Before that, on Pentium, produced 1993, there were U and V pipelines: dual pipe lines that could execute two simple instructions at one clock cycle if they didn't depend on one another; but this was nothing to compare of what is Out-of-Order Execution & Register Renaming appeared in Pentium Pro, and almost left unchanged nowadays.

To explain in a few words, fastest code is where instructions do not depend on previous results, e.g. you should always clear whole registers (by movzx) or use add rax, 1 instead or inc rax to remove dependency on previous state of flags, etc.

You can read more on Out-of-Order Execution & Register Renaming if time permits, there is plenty information available in the Internet.

There are also other important issues like branch prediction, number of load and store units, number of gates that execute micro-ops, etc, but the most important thing to consider is namely the Out-of-Order Execution.

Most people are simply not aware about the Out-of-Order Execution, so they write their assembly programs like for 80286, expecting their instruction will take a fixed time to execute regardless of context; while C compilers are aware of the Out-of-Order Execution and generate the code correctly. That's why the code of such unaware people is slower, but if you will become aware, your code will be faster.

Without giving any specific example or profiler evidence, you can write better assembler than the compiler when you know more than the compiler.

In the general case, a modern C compiler knows much more about how to optimize the code in question: it knows how the processor pipeline works, it can try to reorder instructions quicker than a human can, and so on - it's basically the same as a computer being as good as or better than the best human player for boardgames, etc. simply because it can make searches within the problem space faster than most humans. Although you theoretically can perform as well as the computer in a specific case, you certainly can't do it at the same speed, making it infeasible for more than a few cases (i.e. the compiler will most certainly outperform you if you try to write more than a few routines in assembler).

On the other hand, there are cases where the compiler does not have as much information - I'd say primarily when working with different forms of external hardware, of which the compiler has no knowledge. The primary example probably being device drivers, where assembler combined with a human's intimate knowledge of the hardware in question can yield better results than a C compiler could do.

Others have mentioned special purpose instructions, which is what I'm talking in the paragraph above - instructions of which the compiler might have limited or no knowledge at all, making it possible for a human to write faster code.

csdnceshi63
elliott.david Modern compilers do a lot, and it would take way too long to do by hand, but they're nowhere near perfect. Search gcc or llvm's bug trackers for "missed-optimization" bugs. There are many. Also, when writing in asm, you can more easily take advantage of preconditions like "this input can't be negative" that would be hard for a compiler to prove.
4 年多之前 回复
weixin_41568183
零零乙 "it can try to reorder instructions quicker than a human can". OCaml is known for being fast and, surprisingly, its native-code compiler ocamlopt skips instruction scheduling on x86 and, instead, leaves it up to the CPU because it can reorder more effectively at run-time.
8 年多之前 回复
csdnceshi72
谁还没个明天 Generally, this statement is true. The compiler does it's best to DWIW, but in some edge cases hand coding assembler gets the job done when realtime performance is a must.
11 年多之前 回复
共28条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问