Remove bounds checking for the entire program

I don’t need bound checking.

Instead of writing @inbounds everywhere, can I test my program without it and then, when it all works, enable a flag which disables all the bound checking and other automatic behaviours typical of debugging phase?

Run julia with --check-bounds=no.

3 Likes

Thanks.

Are there any other automatic checks I’m not aware of I need to disable after the debugging phase?

No, vs e.g. C and C++, fast languages, Julia has no added overhead, except that and garbage collection (GC), which is automatic, yes (and avoiding it totally possible, but not for idiomatic code), but GC is not usually thought of as a check, it’s more like a scan, though happens in different threads as of 1.10, and doesn’t directly slow down the main computation, in your other threads. When your memory allocations are no longer reachable, they are freed by it, and the (invisible) allocations, and freeing are as fast, but knowing the can be freed is an overhead. You can reduce it with not allocating as much, e.g. in a loop, preallocating, manually, or use Bumper.jl.

Just profile your code, and see what’s slow, and only worry about hot code, i.e. I do not recommend turning off bounds checking in general. Use e.g. eachindex(A), not 1:length(A) to allow implied @inbounds and for better (more general) code.

GC can actually be faster, because in many other languages, e.g. C and C++, too many allocations happen (because of e.g. unneeded string copying, why immutable strings in Julia are a good thing), and freeing isn’t batched, so GC is not necessarily slower. Untuned code there is often slower. [Mojo has earlier freeing than C++ (or Julia), in its spec, and it can be a good thing, I think it may enable stack allocations, similar to Bumper then.]

At least some C++ compilers do extra optimizations (or this one I recall), i.e. to use FMA, that Julia doesn’t do automatically, so you must use it manually if it applies. Julia makes optimization possible, not possible in C++.

1 Like

I was thinking of disabling the gc too, but didn’t know if gc_enable flag could be used for the entire program. I’m learning to preallocate as much as I can, as I can see an advantage doing this.

I don’t know if there are operations I’m not aware of, which temporary allocate memory and leave dead bytes here and there, or libraries which do this as well. So I don’t know if it’s convenient.

I usually use GB of arrays (few arrays, but they are really big) and recicle them through the code.

Bounds checking is not something one needs to “disable after the debugging phase”. Even if you were to be absolutely sure in the correctness of your code, --check-bounds=no can result in worse performance, due to disabling many compiler optimizations. At least with the current implementation.

I don’t see this being advantageous. If you don’t need the GC (because you don’t allocate much), I don’t think disabling it can improve performance. But you could cause memory leaks by disabling it, if you overlook some allocation.

3 Likes

if you aren’t allocating, gc doesn’t do anything and therefore doesn’t have a performance cost (this is technically slightly a lie, but the true version is gc does have a slight performance cost but not one that you recover by turning off gc)

2 Likes

That would be Bumper.jl do look into it. Allocations aren’t strictly bad because of the GC only, also indirectly, because not done on a stack, rather the heap.

You want to enable SIMD processing, it often happens automatically, but at least not program in a way that disables it. I believe that’s an indirect result of some allocations. Also if e.g. opting into overflow checks (or not using the machine number types), why Julia doesn’t by default.

Thanks to all

1 Like