Search code examples
performancebooleanjuliaboolean-operations

Performance with Julia. Looping through boolean data


N = 100000
a = randbool(N)
b = randbool(N)

Here is my current code (the slow part of my code)

onefalse = a $ b
twofalses = !a & !b
sum(onefalse)
sum(twofalses)

Is there any way to improve this code? I am feeling like I am looping twice through a and through b. I tried with a for loop and if statements but it was way slower.

for i = 1:N
        if a[i]
            if b[i]

            else
                onefalse+=1
            end
        else
            if b[i]
                onefalse+=1
            else
                twofalses+=1
            end
        end
       end

Solution

  • First of all, a valid question is why is the for loop version slow. Its partly because randbool gives a BitArray, not a normal array. I decided to compare with Array{Bool} out of curiosity. I was able to speed it up a bit - I think you are probably at the limits of what is possible though. In particular, indexing into an Array{Bool} seems to be faster than BitArray, but operations on BitArrays like those done here are hard to beat.

    function countfalse1(N, a, b)
        return sum(a $ b), sum(!a & !b)
    end
    
    function countfalse2(N, a, b)
        return N-sum(a), N-sum(a|b)
    end
    
    function countfalse3(N, a, b)
        onef, twof = 0, 0
        @inbounds for i = 1:N
            if a[i]
                if !b[i]
                    onef += 1
                end
            else
                if b[i]
                    onef += 1
                else
                    twof += 1
                end
            end
       end
       return onef, twof
    end
    
    srand(1000)
    N = 10000000
    a = randbool(N)
    b = randbool(N)
    c = Bool[a[i] for i in 1:N]
    d = Bool[b[i] for i in 1:N]
    
    println("BitArray")
    @show countfalse1(N, a, b)
    @time countfalse1(N, a, b)
    @time countfalse1(N, a, b)
    @time countfalse1(N, a, b)
    
    @show countfalse2(N, a, b)
    @time countfalse2(N, a, b)
    @time countfalse2(N, a, b)
    @time countfalse2(N, a, b)
    
    @show countfalse3(N, a, b)
    @time countfalse3(N, a, b)
    @time countfalse3(N, a, b)
    @time countfalse3(N, a, b)
    
    println("\nArray{Bool}")
    @show countfalse1(N, c, d)
    @time countfalse1(N, c, d)
    @time countfalse1(N, c, d)
    @time countfalse1(N, c, d)
    
    @show countfalse2(N, c, d)
    @time countfalse2(N, c, d)
    @time countfalse2(N, c, d)
    @time countfalse2(N, c, d)
    
    @show countfalse3(N, c, d)
    @time countfalse3(N, c, d)
    @time countfalse3(N, c, d)
    @time countfalse3(N, c, d)
    

    gives

    BitArray
    countfalse1(N,a,b) => (5001756,2500026)
    elapsed time: 0.004565573 seconds (5014328 bytes allocated)
    elapsed time: 0.003607561 seconds (5000528 bytes allocated)
    elapsed time: 0.013880181 seconds (5000528 bytes allocated, 83.83% gc time)
    countfalse2(N,a,b) => (5003620,2500026)
    elapsed time: 0.000784883 seconds (1250240 bytes allocated)
    elapsed time: 0.000752576 seconds (1250240 bytes allocated)
    elapsed time: 0.000758695 seconds (1250240 bytes allocated)
    countfalse3(N,a,b) => (5001812,2500026)
    elapsed time: 0.120491323 seconds (144 bytes allocated)
    elapsed time: 0.118401949 seconds (144 bytes allocated)
    elapsed time: 0.11807728 seconds (144 bytes allocated)
    
    Array{Bool}
    countfalse1(N,c,d) => (5001756,2500026)
    elapsed time: 0.098838752 seconds (40000640 bytes allocated)
    elapsed time: 0.112468122 seconds (40000640 bytes allocated, 10.64% gc time)
    elapsed time: 0.11305269 seconds (40000640 bytes allocated, 10.22% gc time)
    countfalse2(N,c,d) => (5003620,2500026)
    elapsed time: 0.066169587 seconds (10000328 bytes allocated)
    elapsed time: 0.084794646 seconds (10000328 bytes allocated, 17.78% gc time)
    elapsed time: 0.067458965 seconds (10000328 bytes allocated)
    countfalse3(N,c,d) => (5001812,2500026)
    elapsed time: 0.066095076 seconds (144 bytes allocated)
    elapsed time: 0.067585543 seconds (144 bytes allocated)
    elapsed time: 0.06718118 seconds (144 bytes allocated)