# Removing bounds checking for HPC - \`--check-bounds=unsafe\`?

**URL:** <https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897>\
**Category:** Julia at Scale\
**Tags:** performance, hpc, inbounds, bounds-check\
**Created:** [January 18, 2025, 2:28pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897 "2025-01-18T14:28:27Z")\
**Posts on this page:** 12\
**Page:** 3

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [January 23, 2025, 5:22pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/41 "2025-01-23T17:22:38Z")

</div>

> [@danielwe](#):
>
> I recommend carefully reading @Sevi’s post about `Base.@propagate_inbounds` above: [Removing bounds checking for HPC - `--check-bounds=unsafe`? - #25 by Sevi](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/25) Perhaps you can reduce the number of `@inbounds` by punting them a level or two up the call stack? Ideally every `@inbounds` will be placed right at the point where it’s most obvious from the code that the indices are actually inbounds, and then `Base.@propagate_inbounds` will make sure it propagates down to the actual indexing expression.

I agree that the process you describe would result in the ‘best code’ in some sense. I think we have a bit of a cultural disconnect here though. Pragmatically, given limited time (and possibly limited Julia-coding expertise), I’m aiming for good-enough code that is as easy as possible to write and maintain (and teach students and other new users to contribute to). For me, and I think many HPC-using scientists, ‘good enough’ does include ‘the best performance we can get’, even if that involves compromises on safety.

My point is that that pragmatic, good-enough experience for an HPC scientist has been pretty good in Julia, but the ongoing failure of `--check-bounds=no` is making it worse, and requiring boiler-plate code around every performance-critical function is making the experience worse in a different way (in terms of the developer productivity and learning curve rather than code performance), but it is for me (us?) a very significant way.

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [January 23, 2025, 5:38pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/42 "2025-01-23T17:38:02Z")

</div>

I agree. The use-case is for code has already been tested millions of times with bounds checking,

Why not let the user globally turn them off? Maybe it is even slower due to missing compiler optimizations, but fine. Let the user check and see.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [January 23, 2025, 5:50pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/43 "2025-01-23T17:50:06Z")

</div>

> [@johnomotani](#):
>
> I think we have a bit of a cultural disconnect here though.

No I totally understand. It’s a boiler plate-heavy solution and an especially tough sell in an environment where you’re continually onboarding students who need to get up to speed quickly. I don’t see a perfect solution, but hopefully the compiler will keep getting smarter and make `@inbounds` less relevant, and perhaps it’s possible to make linting clever enough to emit warnings like “the compiler will struggle to optimize this loop; click this link for 3 simple steps to writing fast loops” (with an emphasis on _simple_, and where the first two steps are things that often help make `@inbounds` irrelevant, while the third is to use `@inbounds`)

---

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [January 31, 2025, 5:14pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/44 "2025-01-31T17:14:43Z")

</div>

Just to add some more motivation - while I was testing various options I found another type of run with our simulation code where removing bounds checks results in a 2x speed-up. We really can’t do without that!

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [January 31, 2025, 10:56pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/45 "2025-01-31T22:56:25Z")

</div>

extremely noob question: I see a lot of commentary along the lines of “removing bounds checking before compilation makes the compilation more challenging and do weird things”

but is it be fair to say that bounds-checking operations are mostly self contained and recognizable? what would be the difficulties involved in a process like

- compiling the code with all bounds checks on as per default, ignore `@inbounds`
- afterwards, go through the generated code (maybe LLVM level?) and delete any lines corresponding to bounds checks
  - accept the fact that OOB access may happen and crash

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [February 1, 2025, 12:00am UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/46 "2025-02-01T00:00:07Z")

</div>

I think this is probably what we should do. It wouldn’t be too hard, but will roughly double compilation time (since you need to compile all the code with checkbounds=true first).

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 1, 2025, 3:11am UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/47 "2025-02-01T03:11:47Z")

</div>

> [@adienes](#):
>
> accept the fact that OOB access may happen and crash

> [@Oscar\_Smith](#):
>
> double compilation time (since you need to compile all the code with checkbounds=true first)

I don’t think either of these are acceptable, I’d rather keep a convenient compiler flag used after I put in safeguards that a call-wise compiler might miss. It’s also worth pointing out that `--checkbounds=no` is not equivalent to removing boundschecking from compiled code; see [Consider removing `--check-bounds=no`? · Issue #48245 · JuliaLang/julia](https://github.com/JuliaLang/julia/issues/48245), where OP has continued discussion. The performance gains or losses of `--check-bounds=no` or `@inbounds` have also been observed to be platform-dependent. Granted, it’s not difficult to make a Julia program that indexes arrays so much that `--check-bounds-no` speeds it up across all platforms.

> [@johnomotani](#):
>
> For my code (and I imagine many scientific codes) we iterate through arrays in funky ways - e.g. my finite-element methods requires operations on overlapping sub-blocks like 1:5, 5:9, 9:14, etc. I would be amazed if any compiler would ever prove that these things are safe!

Indeed, you would need `eachindex` or `axes` to give the compiler the opportunity, which basically serves to move boundschecking out of hot loops. The compiler can also stop at function barriers, so it can’t elide boundschecking for something as simple as `@noinline index1(a::Array) = a[1]`.

> [@johnomotani](#):
>
> give us the ability to `@inbounds` an entire package or module

That can’t do the same thing as a compiler flag like `--checkbounds=no`, as imported modules and packages without `@inbounds` would still be compiled and precompiled with boundschecking. If you want to look into that anyway, several macros including `@inbounds` can’t take module expressions as inputs because they assign the input code to a temporary variable. You also can’t do `module Name @inbounds begin ... end end` because that at best only elides boundschecking for code _executed_ within the module expression, which it currently doesn’t seem to do at the global scope anyway. `@inbounds` doesn’t happen to make this easy, we’d need a macro that adds `@inbounds` inside methods.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [February 1, 2025, 4:07am UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/48 "2025-02-01T04:07:30Z")

</div>

> [@Benny](#):
>
> I don’t think either of these are acceptable,

but if it’s opt-in, why not? if some users want to use a flag `--posthoc-strip-out-all-boundschecks-at-the-risk-of-segfaults-and-long-compile-times` why shouldn’t that be an available feature?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 1, 2025, 4:32am UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/49 "2025-02-01T04:32:42Z")

</div>

I provided my reasons for preferring `--checkbounds=no`, so I’m not sure what you’d like me to clarify. I’ll hazard a guess that you’re trying to argue risky code should be an option, but the absence or removal of boundschecking typically isn’t intended to make memory-unsafe code, just eliminate unnecessary overhead after ensuring inbounds access in other ways. That applies just as much to `--checkbounds=no`. Silent errors, vulnerabilities, or crashes upon unvalidated inputs are considered bugs, and it’d be especially terrible for HPC.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [February 1, 2025, 4:50am UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/50 "2025-02-01T04:50:34Z")

</div>

> Silent errors, vulnerabilities, or crashes upon unvalidated inputs are considered bugs

is it really a bug if it comes with a huge disclaimer in the docs?

I am not defending specifically the existence of `--checkbounds=no` ; I don’t know enough about the implementation details to have a strong opinion. But in more general terms a tool that takes compiled code and excises everything that looks like a boundscheck seems like a pretty reasonable desire.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 1, 2025, 5:08am UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/51 "2025-02-01T05:08:12Z")

</div>

> [@adienes](#):
>
> is it really a bug if it comes with a huge disclaimer in the docs?

You can argue that it isn’t, but again, it’s irrelevant to my preference for `--checkbounds=no`.

> [@adienes](#):
>
> takes compiled code and excises everything that looks like a boundscheck seems like a pretty reasonable desire.

As mentioned, the `--checkbounds` flag affecting other compiler optimizations is the problem. I don’t know why `--checkbounds=no` must obstruct constant folding, and this could be [LLVM behavior](https://stackoverflow.com/questions/37514909/why-does-my-code-run-slower-when-i-remove-bounds-checks) that Julia can’t do much about. Consider the flip side, assuming inbounds access also opens up compiler optimizations like SIMD. Retroactively removing boundschecking from compiled code doesn’t add those optimizations, so we’d have to truly recompile anyway.

---

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [February 1, 2025, 4:05pm UTC](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897/52 "2025-02-01T16:05:26Z")

</div>

> [@Benny](#):
>
> That can’t do the same thing as a compiler flag like `--checkbounds=no`, as imported modules and packages without `@inbounds` would still be compiled and precompiled with boundschecking.

That’s probably an acceptable compromise - it would be for me. I’m OK with assuming that external packages (e.g. LinearAlgebra, etc.) would optimise appropriately and use `@inbounds` themselves when it is likely to improve performance. Being able to `@inbounds` all the code in my own project is what I want. [If it was possible to use `@inbounds` on an entire module, and a package can, at the moment, only be used with best performance with `--check-bounds=no`, then that package should `@inbounds` itself, and warn users to test with `--check-bounds=yes`. I guess that would be an unusual case though.]

> [@Benny](#):
>
> the absence or removal of boundschecking typically isn’t intended to make memory-unsafe code, just eliminate unnecessary overhead after ensuring inbounds access in other ways. That applies just as much to `--checkbounds=no`. Silent errors, vulnerabilities, or crashes upon unvalidated inputs are considered bugs, and it’d be especially terrible for HPC.

This is true, but dealing with the fact that there would be undefined behaviour for an out-of-bounds array access is a very well-established and accepted part of working in HPC. We are all limited by the compute-time budget we have on whatever HPC cluster(s) we are using, so will spend the time to check correctness of indexing and verify inputs sufficiently to avoid out-of-bounds accesses during development and testing, before deploying the large simulations that provide scientific output. It’s for those large simulations where paying the cost of bounds-checking is not worth it, and so it is worth doing the work up front to not need bounds-checking.

[Previous page](https://discourse.julialang.org/t/removing-bounds-checking-for-hpc-check-bounds-unsafe/124897.md?page=2)
