Live data from Hacker News

Inline assembly in Linux

github.com

21–30 of 36 posts

Re: Inline assembly in Linux

#21
post #4

I've been using a lot of inline assembly lately, and while the Stockholm syndrome might be in effect, I'm coming to like the GCC syntax. For me, main thing that has helped has been to adopt a consistent syntax. Here's some examples of what I'm currently using for an AVX2 popcnt optimization, with some explanation. #define ASM_VEC_BYTE_COUNT_SET(vec, sum, mask, shuf) \ __asm volatile ("vpsrld $4, %[VEC], %[SUM]\n" \ "…

Cannot disagree more about #3. You almost never want asm volatile. The compiler is mostly doing data flow analysis, and I've seen so many programmers who don't understand that. So, if the compiler's data flow analysis doesn't put your asm block where you want, you just give up and put "volatile" on it. NO! Just let the compiler figure it out. You may be smarter about generating the assembly in this case, but the comp…

I understand that most others share your position, and mostly agree when it comes to volatile variables. I'd also agree with you if removing "volatile" caused the code to break. But I think that it can be necessary for performance, and don't think that there are true downsides. I believe if you are using assembly it is because you don't want the compiler to attempt any further optimizations. For the cases when I want to drop to assembly, it's because I've already decided the register allocation and instruction ordering I want, and will verify the assembly that is generated.

My goal is to "lock in" an established level of performance once I've achieved it, so that compiler upgrades or changes don't result in performance drops. I often compare the output of multiple compilers with a matrix of optimization flags, choose the best blocks from each, and then hand-optimize from there while cross-referencing Agner's handbooks with Likwid's performance reports. If I've chosen to use inline assembly, the chances that the compiler will succeed in further optimizing my code is very low.

I realize it's not a popular view, but I think that using volatile with __asm is usually the correct approach. If you don't need "volatile", you probably should be using an intrinsic instead. I think the alternative (which may in fact be the better solution) is dropping to straight assembly for the entire function or distributing binary code.

Re: Inline assembly in Linux

#22

Earlier quoted context omitted.

I don't understand, but I'd like to. To create a continuation, we need to copy the entire stack, by definition. But "the stack" is just an array of bytes. It's all the bytes between the current stack pointer and the "root" stack frame. So to create a continuation, copy these bytes and stash them somewhere, then set up a longjmp target to the current instruction. To apply a continuation, i.e. to restore the stack, we…

The Lua implementation is a C library. You invoke it by calling C functions like lua_call(). Imagine you have a C program like this: #include int main() { for (int i = 0; i Now imagine that internally, fancylib uses Lua. So fancylib_calculate() calls lua_call(). Now imagine that the Lua function run by fancylib decides to use continuations. When you call fancylib_calculate(0), it creates a continuation. And when you…

When using lua_pcall (in 5.2 and above) you can provide a continuation function. Would that solve the dilemma?

Re: Inline assembly in Linux

#23

I'm trying to add call/cc to node, or to lua. Recap: call/cc is the ability to save the current state of a running thread, then revert to that state at a later point in time. In other words, at any point in your program, you can say "Save the current stack." It's saved as a function. Later, whenever you call that function, the current stack is thrown out, and replaced with the saved stack. This is very useful for a n…

If you want to actually clone the stack, you're probably stuck.

If you want to use this to do something that takes multiple invocations of lua_resume to complete without the calling Lua code being aware, you might be able to use lua_yieldk.

Re: Inline assembly in Linux

#24
Is it ever the case that inline assembly is required over separate object sources just in assembly? I would have thought it would be preferred to not use inline assembly, and simply link in object files of what you need. It would seem simpler syntax-wise, too. Why prefer inline assembly?

Re: Inline assembly in Linux

#25
post #21

Earlier quoted context omitted.

Cannot disagree more about #3. You almost never want asm volatile. The compiler is mostly doing data flow analysis, and I've seen so many programmers who don't understand that. So, if the compiler's data flow analysis doesn't put your asm block where you want, you just give up and put "volatile" on it. NO! Just let the compiler figure it out. You may be smarter about generating the assembly in this case, but the comp…

I understand that most others share your position, and mostly agree when it comes to volatile variables. I'd also agree with you if removing "volatile" caused the code to break. But I think that it can be necessary for performance, and don't think that there are true downsides. I believe if you are using assembly it is because you don't want the compiler to attempt any further optimizations. For the cases when I want…

Yes, that is really a better solution: to write the whole function in assembly. "volatile" is just a poor substitute for that.

Re: Inline assembly in Linux

#26

Is it ever the case that inline assembly is required over separate object sources just in assembly? I would have thought it would be preferred to not use inline assembly, and simply link in object files of what you need. It would seem simpler syntax-wise, too. Why prefer inline assembly?

There's several macros in the kernel which contain inline assembly, and you can't use code written in assembly because it would require using the stack to call the function (the case I'm thinking of is the switch_to macro which switches between tasks in the kernel).

Re: Inline assembly in Linux

#27
Having lived my development life so far removed from the actual physical CPU/memory, thinking about implementing this kind of low-level stuff into actual code is mind-boggling to me.

Re: Inline assembly in Linux

#28

Earlier quoted context omitted.

The Lua implementation is a C library. You invoke it by calling C functions like lua_call(). Imagine you have a C program like this: #include int main() { for (int i = 0; i Now imagine that internally, fancylib uses Lua. So fancylib_calculate() calls lua_call(). Now imagine that the Lua function run by fancylib decides to use continuations. When you call fancylib_calculate(0), it creates a continuation. And when you…

If you restore the entire C stack to resume the Lua continuation, it will reset the loop in main() to i=0! That's the point of continuations, though. That's a feature, not a bug. When you create a continuation, you're saying "whatever happens after this, allow me to do it again at some later time." If the calling library happened to be in a loop, then the goal is to serialize that loop so that it can be invoked again…

> That's the point of continuations, though. That's a feature, not a bug.

If that's what you're after, then by all means implement that. :) But I think most people would expect the Lua interpreter state to be self-contained, and not to affect the state of the surrounding C execution environment.

Re: Inline assembly in Linux

#29
post #21

Earlier quoted context omitted.

I understand that most others share your position, and mostly agree when it comes to volatile variables. I'd also agree with you if removing "volatile" caused the code to break. But I think that it can be necessary for performance, and don't think that there are true downsides. I believe if you are using assembly it is because you don't want the compiler to attempt any further optimizations. For the cases when I want…

Yes, that is really a better solution: to write the whole function in assembly. "volatile" is just a poor substitute for that.

Other than the "code smell", what do you see as the main dangers of using "__asm volatile" rather than just "__asm"? Assuming that there are cases where I do get significantly better performance from specifying the exact ordering of instructions, what can I do to minimize these dangers while keeping the better performance?

Re: Inline assembly in Linux

#30
GCC inline assembly is one of the most terrible things I've ever had to work with. Somebody seriously need to redesign it or replace it. Aside from that,a decent reference manual for the existing version would be welcome.
Post reply on HN