Live data from Hacker News

Push Ifs Up and Fors Down

matklad.github.io

101–110 of 209 posts

Re: Push Ifs Up and Fors Down

#101
Ifs = control flow

Fors = data flow / compute kernel

it makes sense to keep control flow and data flow separated for greater efficiency, so that you independently evolve either of flows while still maintaining consistent logic

Re: Push Ifs Up and Fors Down

#102

Earlier quoted context omitted.

You can't shove every single assumption into the type system...

[flagged]

  > with admirable tunnel vision, bullheadedness and mission for maximally general algebraic and arbitrary constraint type systems.
I believe they're called keyhole optimizations, greedy search, and "the customer is always right..."

Re: Push Ifs Up and Fors Down

#104
A compiler that can prove that the condition-within-loop is constant for the duration of the looping, can lift up that condition branching, and emit two loops.

But I like to help the compiler with this kind of optimization, by just doing it in the code. Let the compiler focus on optimizations that I can't.

Re: Push Ifs Up and Fors Down

#105

My weird mental model: You have a tree of possible states/program flow. Conditions prune the tree. Prune the tree as early as possible so that you have to do work on fewer branches. Don’t meticulously evaluate and potentially prune every single branch, only to find you have to prune the whole limb anyways. Or even weirder: conditionals are about figuring out what work doesn’t need to be done. Loops are the “work.” Ul…

Can I float an adjacent model? Classes are nouns, functions are verbs.

Re: Push Ifs Up and Fors Down

#106
post #85

I strongly disagree with this ifs take. I want to validate data where it is used. I do not trust the caller (myself) to go read some comment about the assumptions on input data a function expects. I also don't want to duplicate that check in every caller.

One option is to use asserts that are only included in debug builds. That way any incorrect call of the function will crash the program in debug builds, but will have the performance benefits of the lifted conditional checks in release builds.

You'll end up duplicating the condition, but that seems like a reasonable price to pay for correct and performant software.

Re: Push Ifs Up and Fors Down

#107
post #43

Sometimes I like to put the conditional logic in the callee because it prevents the caller from doing things in the wrong order by accident. Like for example, if you want to make an idempotent operation, you might first check if the thing has been done already and if not, then do it. If you push that conditional out to the caller, now every caller of your function has to individually make sure they call it in the rig…

You’ve kind of answered your own question here. > If you push that conditional out to the caller, now every caller of your function has to individually make sure they call it in the right way to get a guarantee of idempotency In this situation your function is no longer idempotent, so you obviously can’t provide the guarantee. But quite frankly, if you’re having to resort to making individual functions implement stat…

Probably implicit in your #2, but there are two types of people in the world: people who know why you shouldn't try to write a production-grade database from scratch, and people who don't know why you shouldn't try to write a production-grade database from scratch. Neither group should try to write a production-grade database from scratch.

Re: Push Ifs Up and Fors Down

#108
post #9

Earlier quoted context omitted.

The way to solve this is to split decisions from execution and that’s a notion I got from our old pal Bertrand Meyer. if (weShouldDoThis()) { doThis(); } It complements or is part of functional core imperative shell. All those checks being separate makes them easy to test, and if you care about complexity you can break out a function per clause in the check.

Functions should decide or act, not both.

But if that’s all you have, then how does your system do anything ? You ultimately need to be able to decide and then act based in that decision somewhere..

Re: Push Ifs Up and Fors Down

#109

Earlier quoted context omitted.

This is why we invented type systems. No need to examine call chains, just examine input types. The types will not only tell you what assumptions you can make, but the compiler will even tell you if you make an invalid assumption!

You can't shove every single assumption into the type system...

You can at least shove them into the constructors.

Re: Push Ifs Up and Fors Down

#110
In some cases you want to do the opposite - to utilize SIMD.

With AVX-512 for example, trivial branching can be replaced with branchless code using the vector mask registers k0-k7, so an if inside a for is better than the for inside the if, which may have to iterate over a sequence of values twice.

To give a basic example, consider a loop like:

    for (int i = 0; i 
We can convert this to one which operates on 16 ints per loop iteration, with the loop body containing no branches, where each int is only read and written to memory once (assuming length % 16 == 0).

    __mmask16 consequents;
    __mmask16 alternatives;
    __mm512i results;
    __mm512i ones = _mm512_set1_epi32(1);
    __mm512i twos = _mm512_set1_epi32(2);
    for (int i = 0; i 
Ideally, the compiler will auto-vectorize the first example and produce something equivalent to the second in the compiled object.
Post reply on HN