frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

Open in hackernews

SIMD-friendly algorithms for substring searching (2018)

http://0x80.pl/notesen/2016-11-28-simd-strfind.html
164•Rendello•15h ago

Comments

ncruces•11h ago
I implemented these in my attempt to SIMD optimize Wasm/WASI libc.

https://github.com/ncruces/go-sqlite3/tree/main/sqlite3/libc

For known haystack lengths, and large needles, I found it useful to augment the approach with Quick Search.

https://igm.univ-mlv.fr/~lecroq/string/node19.html

clauderoux•11h ago
I implemented many different algorithms for searching and splitting strings using SMID methods as well: https://github.com/naver/tamgu/blob/06aedf2f14895925d7b5a8e2... I used a different algorithm than the ones presented here.
ncruces•10h ago
Could you summarize your algorithm? Like a high-level description?

Like algorithm 1 (from the article) checks N possible positions at a time by matching the first and last character; algorithm 2 instead tests the 4 leading characters.

Rendello•3h ago
I tried to implement a modified version for LZ77 window search with Zig's generic SIMD a few years ago:

https://news.ycombinator.com/item?id=44273983

rurban•9h ago
We know that the libc strstr performs horrible, but musl is fast and state of the art.

Now we just need a name, and we can add it to the smart shootout. Wonder how it compares to the best SIMD algos

ncruces•8h ago
If you're interested in a rough benchmark, I compared musl's “two way” with a variation on this algorithm for my SIMD optimized libc linked in a sister comment.

The benchmark involves finding this line in that file: https://github.com/ncruces/go-sqlite3/blob/v0.26.1/sqlite3/l...

The improvements over musl are in this table: https://github.com/ncruces/go-sqlite3/tree/v0.26.1/sqlite3/l...

I'd say it's a decent improvement, if not spectacular. musl does particularly well with known length strings (memmem), whereas I'm allowed to cheat for unknown length strings (strstr) because the Wasm environment allows me to skirt some UB.

The NUL terminated string curve ball wrecks many good algorithms.

MattPalmer1086•7h ago
Would be good to have more SIMD algorithms in smart. Maybe I'll have a play with it if I get time.
MattPalmer1086•5h ago
Looking at them, would need a little work to make them safe (not reading past needle or haystack). Probably not too much effort, may need a different search for data mod block size at the end.
mgaunard•9h ago
missing (2018) ?
sylware•8h ago
What is the string sizes thresold for efficiency?

Because the SIMD (aligned, size computations, etc) setup code is usually more expensive that byte-oriented basic search for "small" strings.

Yes, it depends heavily on the hardware architecture.

ncruces•8h ago
Here, it's often the opposite.

These algorithms are basically brute force with very little setup, and can become quadratic for large, periodic needles.

String search algorithms that avoid quadratic behaviour (and may even be sublinear) have an higher cost setup that explores needle structure

sylware•7h ago
What? It all depends on the sizes of the strings. Hardware benchmarks, for each significant hardware µarchitectures, must be done on combinations of string sizes in order to know "when" the SIMD setup code is worth it.

Often the setup code is not worth it, even the SIMD complexity is not bringing enough performance in many use cases (basically, kept for niche applications, little lib statically linked for those).

ncruces•5h ago
Did you look at the algorithm 1? The setup code is a pair of splats. There's no consideration for alignment, it works with unaligned data just fine. So what do you mean? What threshold would you expect for it to be worth it (assuming it's useful at all)?
sylware•5h ago
Dude, I cannot be more explicit than that.

That said, when you work on such code, use assembly, C code is for reference (have a look at dav1d av1 decoder).

burntsushi•4h ago
What? You don't have to do that. Hell, the SIMD code that ripgrep uses is written in Rust.
ncruces•4h ago
I can't either.

Having implemented this, I'll claim that this is already competitive for needles as small as 2 bytes, and if the needle doesn't show up in the first couple “vector sizes” of the haystack.

Also, look at burntsushi's comment. They use this algorithm for similarly small sizes. They do use Rabin-Karp for “supremely short haystacks” (just because that lib is awesome and uses every trick in the book), but that wording should give you an idea of how small the threshold will be.

And really, how common are “supremely small” haystacks?

eska•7h ago
The swar algorithm has UB because it casts the 1 byte aligned data to 8 byte aligned. Perhaps it suffers some performance issues from unaligned loads?
burntsushi•4h ago
I always took these as "idealized" algorithms or pseudo-code. In addition to not doing correct unaligned loads (using `memcpy`), the boundary checks are wrong. The code assumes the length of the haystack is a multiple of 8. Additionally, if the needle is empty, you'll get unsigned integer overflow leading to an out-of-bounds access on the needle. That's three different ways to get UB.

This is pretty common in my experience when demonstrating SIMD code. Often only the relevant bits are shown, and not a lot of effort is given to getting the boundary cases correct. It's rarely acknowledged explicitly, but I would assume it's because the boundary conditions are somewhat less interesting than the "meat" of how to use vectors in an interesting way.

Rendello•3h ago
When I modified the idealized algorithm to suit my needs a few years ago, I learned just how painful the boundary cases are. I realized I didn't want to ever touch SIMD string searching unless:

- I had a very specific use-case that I really needed SIMD for and was willing to really invest a lot in it; or

- The work had already been done for me in a generic sense and I could reap the fruits of that labour (ripgrep / Rust Regex, thanks for that by the way)

eska•3h ago
True. The size assumption is mentioned in the article however. The simd library by agner makes the same assumption and demands that the user over-allocates their data
burntsushi•6h ago
The "AVX2 (generic)" approach is roughly what ripgrep uses (via Rust's `regex` crate) to accelerate most searches. Even something like `\w+\s+Sherlock\s+\w+` will benefit since ripgrep will pluck `Sherlock` out of the regex and search that.

The actual implementation is here: https://github.com/BurntSushi/memchr?tab=readme-ov-file#algo...

The main difference with the algorithm presented here is that instead of always using the first and last bytes of the needle, a heuristic is used to try to pick two bytes that occur less frequently according to a background frequency distribution.

It ends up being quite a bit faster than just plain Two-Way or even GNU libc's implementation of `memmem`. From the root of the `memchr` repository:

    $ rebar rank benchmarks/record/x86_64/2023-12-29.csv -e '^rust/memchr/memmem/(oneshot|prebuilt|twoway)' -e '^libc/memmem/oneshot'
    Engine                       Version  Geometric mean of speed ratios  Benchmark count
    ------                       -------  ------------------------------  ---------------
    rust/memchr/memmem/prebuilt  2.7.1    1.07                            57
    rust/memchr/memmem/oneshot   2.7.1    1.39                            54
    libc/memmem/oneshot          unknown  3.15                            54
    rust/memchr/memmem/twoway    2.7.1    5.26                            54
The "prebuilt" benchmarks also demonstrate the API deficiencies of routines like `memmem`. Because of their API, they need to rebuild the state necessary to execute a search for the needle given. But it is often the case that the needle is invariant across repeated calls with different haystacks. So you end up doing that repeated work for no gain.
jakobnissen•2h ago
Interesting. How do you know the background distribution of bytes? Won't a scan of the haystack to get the distribution take up a significant amount of time?
burntsushi•2h ago
It's a _background_ distribution. That is, a guess. A heuristic. It doesn't change with the input.
azhenley•5h ago
Now if I can just use SIMD directly from Python without calling out to another language.
adgjlsfhk1•5h ago
why would you want to? if you are performance bound with Python code, you can pick up a 20-50x performance improvement by switching language.
ashvardanian•2h ago
Hi Austin! Was just checking your blog and the vowels detection post (< https://austinhenley.com/blog/vowels.html>).

What exactly do you mean by “use SIMD directly without calling out to another language”?

In some way Assembly will probably anyways be another language… but that’s a technicality.

I guess the spectrum of SIMD-related work in relation to Python is quite broad. There are projects like PeachPy, to help one write x86 Asm in Python, new Python’esque languages like Mojo, or SIMD libraries with thin CPython bindings. Do you mean one of those?

PS: I’m in the last camp. And in case you are focused on ASCII, for vowel search, have you tried StringZilla’s `find_first_of` (< https://github.com/ashvardanian/StringZilla/blob/960967d78c7...>)? I think it should perform well ;)

klaussilveira•2h ago
Reminds me of https://github.com/nikneym/hparse

Which uses SIMD algos for fast HTTP parsing.

mwsherman•1h ago
C# has implemented some SIMD for IndexOf: https://github.com/dotnet/runtime/pull/63285

Sleep Is for Backpropagation

https://dimitarsimeonov.com/2017/12/22/sleep-is-for-backpropagation
1•ijidak•1m ago•0 comments

Redwood AI: Mobility

https://www.1x.tech/discover/redwood-mobility
1•Brysonbw•3m ago•0 comments

Human-like object concept representations emerge naturally in multimodal LLMs

https://www.nature.com/articles/s42256-025-01049-z
1•frozenseven•6m ago•0 comments

Global Inequality: Branko Milanovic

https://paulkrugman.substack.com/p/global-inequality-branko-milanovic
1•rbanffy•11m ago•0 comments

Grep – AI Context Assistant

https://chromewebstore.google.com/detail/grep-ai-context-assistant/hlkpgngmcneopafpkkceppjnhlnpigbn
1•nitinram•12m ago•3 comments

Biofuels policy has been a failure for the climate, new report claims

https://arstechnica.com/science/2025/06/biofuels-policy-has-been-a-failure-for-the-climate-new-report-claims/
1•gametorch•15m ago•0 comments

The Cost of Free: How AI, Apps, and Crypto Are Exploiting Your Data

https://medium.com/@TonyCletus/the-hidden-cost-of-free-how-ai-apps-and-crypto-are-exploiting-your-data-especially-in-africa-eb0d425d6fc0
2•omojo•16m ago•0 comments

The LLM Engineer's Almanac

https://modal.com/llm-almanac/advisor
1•birdculture•16m ago•0 comments

Mark Zuckerberg's AI hiring spree

https://www.theverge.com/command-line-newsletter/687173/inside-mark-zuckerbergs-ai-hiring-spree
1•gametorch•16m ago•0 comments

RAG Is a Fancy, Lying Search Engine

https://labs.stardog.ai/rag-is-a-fancy-lying-search-engine
2•kendallgclark•22m ago•0 comments

Show HN: UltraXOXO – a tic-tac-toe of tic-tac-toe's

https://www.ultraxoxo.com/
1•ChandSethi•25m ago•0 comments

Ask HN: Indihackers – How do you plan your pricing page?

1•pinter69•25m ago•0 comments

The community builders: Ed Giansante x Michelle Goodall

https://www.michellegoodall.co.uk/insights/meet-the-community-builders-persona-ed-giansante-interview
1•randerson001•28m ago•0 comments

Show HN: Self Modify Retro Website

https://plastic.dunkirk.sh
1•clacker-o-matic•31m ago•0 comments

Children and Educatoin in the United States

https://www.counterpunch.org/2025/06/13/on-children-and-education-in-the-united-states/
1•ludicrousdispla•31m ago•0 comments

Show HN: I built a Mac app to restore Dock-click minimize and avoid tiny buttons

https://idemfactor.gumroad.com/l/click2minimize
3•goofywon•32m ago•1 comments

Ask HN: Will LLMs Replace "Google" as Our Default Search Verb?

2•arkj•34m ago•1 comments

High-volume exercise tied to increased coronary artery calcification score

https://medicalxpress.com/news/2025-05-high-volume-coronary-artery-calcification.html
3•PaulHoule•37m ago•0 comments

How to make StackExchange (and others) more fun

https://rubenerd.com/how-to-make-stackexhange-more-fun/
1•rbanffy•39m ago•0 comments

Show HN: A deep research interface that motivates me to keep exploring

https://www.proread.ai/deepdive
2•kasince2k•41m ago•0 comments

AMD Advancing AI: MI350X and MI400 UALoE72, MI500 UAL256 – SemiAnalysis

https://semianalysis.com/2025/06/13/amd-advancing-ai-mi350x-and-mi400-ualoe72-mi500-ual256/
1•rbanffy•42m ago•0 comments

AI Slop YouTube Channels Telling AI Slop Google About AI Slop Fake Motorcycles

https://www.jalopnik.com/1884156/ai-slop-fake-motorcycle-youtube-channels-in-google-searches/
4•rntn•51m ago•0 comments

Infineon security microcontroller flaw enabled extraction of TPM secret keys

https://it4sec.substack.com/p/a-flaw-in-infineons-security-microcontrollers
2•walterbell•51m ago•0 comments

Self-referential abstractions: A quick look at the wacky epistemology of analog

https://lcamtuf.coredump.cx/blog/abstractions/
1•todsacerdoti•52m ago•0 comments

Show HN: Open-source lightweight CMS on Cloudflare (pages, d1, r2, access)

https://github.com/microfeed
2•wenbin•1h ago•0 comments

Show HN: AnyCrawl v0.0.1-alpha.5 – custom user-agent and richer scraping API

https://github.com/any4ai/AnyCrawl
1•ntbperst•1h ago•0 comments

Drones will realize the promise of suicide terrorism

https://blog.exitgroup.us/p/cheap-drones-will-realize-the-promise
42•arrowsmith•1h ago•51 comments

I Created a Play-by-Play Dataset for the 2007 College Football Season

https://thespade.substack.com/p/i-created-a-play-by-play-dataset
1•nafnlj•1h ago•0 comments

How we built our multi-agent research system

https://www.anthropic.com/engineering/built-multi-agent-research-system
1•tosh•1h ago•0 comments

Exploit a binary with sigreturn oriented programming (SROP)

https://Rog3rSm1th.github.io/posts/sigreturn-oriented-programming/
1•fanf2•1h ago•2 comments