...This is news? You've got a tight loop with a branch, and depending on which way the branch goes, you're going to touch completely different locations in memory. The solution (at least for some problems) is just to lay your data out in memory better - optimal is a binary search tree in an array, like the way heaps are implemented. That's what I did for bcache: http://evilpiepirate.org/git/linux-bcache.git/tree/driv…
Good lord. You didn't read the article _at all_. I have some really ugly things to say to a new poster who cannot be bothered to read an article before trying to show off, but I'll refrain. In the future, read first, think, then comment. You'll be doing everyone else a favor.
Binary search is a pathological case for caches
11–17 of 17 posts
Re: Binary search is a pathological case for caches
#12Earlier quoted context omitted.
If I'm wrong, enlighten me. Thus far all you've got is ad hominem arguments. Anyways, I didn't come here to show off, but I did implement a b+ tree that can do > 1 million random lookups/second on a single core, on a > 100 mb tree. So believe it or not, I might know what I'm talking about.
TL;DR - If your element sizes are powers of two, and your cache is set-associative, you run the risk of set aliasing. Caches always use lower bits of the address as the key, probably because it's really fast. If you have more aliases than there are ways in each set, items will become evicted from the cache. If you do it just right, you can end up with the worst case, and you get 100% cache misses. Therefore even some…
Worrying about stuff not being cached because of associativity is pointless when the last 5-10 levels aren't going to be in cache anyways because they don't fit; those last 5-10 cache misses are going to _utterly dominate_ your search time.
IOW, even if associativity isn't a problem at all, binary searches suck w.r.t. caches - I'm not at all saying they're wrong, just that it's not terribly relevant - if performance matters you need to be doing something other than a binary search.
Re: Binary search is a pathological case for caches
#13...This is news? You've got a tight loop with a branch, and depending on which way the branch goes, you're going to touch completely different locations in memory. The solution (at least for some problems) is just to lay your data out in memory better - optimal is a binary search tree in an array, like the way heaps are implemented. That's what I did for bcache: http://evilpiepirate.org/git/linux-bcache.git/tree/driv…
Not quite. The heap layout has bad spatial locality. Think about the last row of leaves - it occupies the last 50% of the array. The next-to-last-row (all their parents) is in the middle 25%-50%. All those leaves are far away from their parents, and thus the heap is not optimal.
Better is to cluster parents and children into small groups. With clusters of three, two thirds of the time a child will adjacent to its parent.
Re: Binary search is a pathological case for caches
#14...This is news? You've got a tight loop with a branch, and depending on which way the branch goes, you're going to touch completely different locations in memory. The solution (at least for some problems) is just to lay your data out in memory better - optimal is a binary search tree in an array, like the way heaps are implemented. That's what I did for bcache: http://evilpiepirate.org/git/linux-bcache.git/tree/driv…
> Optimal is a binary search tree in an array, like the way heaps are implemented. Not quite. The heap layout has bad spatial locality. Think about the last row of leaves - it occupies the last 50% of the array. The next-to-last-row (all their parents) is in the middle 25%-50%. All those leaves are far away from their parents, and thus the heap is not optimal. Better is to cluster parents and children into small grou…
The beautiful thing about the heap layout is that you can prefetch more than one level ahead. If your keys are 4 bytes, 16 of them fit on a cacheline, and you can prefetch 4 levels ahead with a single cacheline.
That means that if nothing is in cache, worst case each loop iteration will take With any kind of clustering (really, it's just a variation on B-trees) you touch less memory but you can't prefetch as far ahead.
In practice I suspect a 4-ary heap would perform better than a binary heap for my application, but there's a bunch of math I'd have to work out again that was hard enough for the binary tree version.
Not quite sure how what you're describing would work, but I can't see offhand how you'd implement it without losing the prefetching the heap layout gives you.
Re: Binary search is a pathological case for caches
#15...This is news? You've got a tight loop with a branch, and depending on which way the branch goes, you're going to touch completely different locations in memory. The solution (at least for some problems) is just to lay your data out in memory better - optimal is a binary search tree in an array, like the way heaps are implemented. That's what I did for bcache: http://evilpiepirate.org/git/linux-bcache.git/tree/driv…
Re: Binary search is a pathological case for caches
#16A Comparison of Cache Aware and Cache Oblivious Static Search Trees Using Program Instrumentation
Re: Binary search is a pathological case for caches
#17Earlier quoted context omitted.
I did read it. And none of that stuff about cache behavior _matters_ when your data isn't in cache and you're spending 70 ns on every loop iteration waiting for the next key to fetch from dram. One of the first things to learn about caches is how dependent modern processors are on prefetching, and a binary search just completely breaks prefetching.
No, you did not. If you had, there is absolutely no way you could have written: "optimal is a binary search tree in an array, like the way heaps are implemented." I leave it to other people to read the article first, then your comment, then vote accordingly. For shame.