Vectorized short circuit operator?

Hi I was wondering if it is possible to apply a short circuit evaluation to 2 bitvectors. Let’s say I want to implement the or operator on 2 bitvectors, I can do that with .|. But this operator is not short circuited. I tried doing it with .|| but this gave me an error. Is there any way around this?

This has been added, it’s included since Julia 1.7.:

https://github.com/JuliaLang/julia/pull/39594

5 Likes

You can do this, but it’s not a good idea. Short-circuit evaluation is there to avoid doing expensive calculations. Evaluating a bitwise or on two bitvectors is as cheap as it gets. Using a short-circuit version will introduce a branch, which is much more expensive, and prevent simd-vectorization.

Example:

julia> @btime (a .| b) setup=(a=bitrand(1024); b=bitrand(1024));
  39.919 ns (2 allocations: 224 bytes)

julia> @btime (a .|| b) setup=(a=bitrand(1024); b=bitrand(1024));
  1.030 μs (3 allocations: 4.41 KiB)

As you can see, the short-circuit version is 25x slower.

If, on the other hand, you have some expensive operations, short-circuiting pays off:

julia> using Primes

julia> @btime isodd.(a) .| isprime.(b) setup=(a=rand(10^3:10^4, 1024);b=rand(10^3:10^4, 1024));
  52.200 μs (127 allocations: 6.34 KiB)

julia> @btime isodd.(a) .|| isprime.(b) setup=(a=rand(10^3:10^4, 1024);b=rand(10^3:10^4, 1024));
  27.400 μs (57 allocations: 5.25 KiB)
9 Likes

In my case it is quite relevant to have a short-circuit evaluation. This is because the second expression only gives an output if the first expression was false. A MWE is shown below:

using Distributions

a = rand(100)
b = rand(100)

c = (b .>= a) .|| (rand.(Bernoulli.(b./a)))

If the expression wasn’t short-circuited it would throw off an error in my case.

But thanks anyways!

1 Like