From 17fd485a3bb82021077c815451bb331bf8ff8f42 Mon Sep 17 00:00:00 2001 From: chethega Date: Sun, 21 Oct 2018 00:16:04 +0200 Subject: [PATCH 1/3] speed up logical indexing by bitarray --- base/bitarray.jl | 1 + base/multidimensional.jl | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 526f027c6aa9b..120ce0b5c93fa 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -84,6 +84,7 @@ IndexStyle(::Type{<:BitArray}) = IndexLinear() const _msk64 = ~UInt64(0) @inline _div64(l) = l >> 6 @inline _mod64(l) = l & 63 +@inline _BLSR(x)= x & (x-1) #zeros the last set bit. Has native instruction on many archs. needed in multidimensional.jl @inline _msk_end(l::Integer) = _msk64 >>> _mod64(-l) @inline _msk_end(B::BitArray) = _msk_end(length(B)) num_bit_chunks(n::Int) = _div64(n+63) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index a24745b952e19..15b676075b05d 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -523,19 +523,23 @@ end L.mask[idx] && return (idx, s) end end -# When wrapping a BitArray, lean heavily upon its internals -- this is a common -# case. Just use the Int index and count as its state. -@inline function iterate(L::LogicalIndex{Int,<:BitArray}, s=(0,1)) - s[2] > length(L) && return nothing - i, n = s +# When wrapping a BitArray, lean heavily upon its internals. +@inline function iterate(L::Base.LogicalIndex{Int,<:BitArray}) + L.sum == 0 && return nothing Bc = L.mask.chunks - while true - if Bc[_div64(i)+1] & (UInt64(1)<<_mod64(i)) != 0 - i += 1 - return (i, (i, n+1)) - end - i += 1 + return iterate(L::Base.LogicalIndex{Int,<:BitArray}, (1, @inbounds Bc[1])) +end +@propagate_inbounds function iterate(L::Base.LogicalIndex{Int,<:BitArray}, s) + Bc = L.mask.chunks + i1, c = s + while c==0 + i1 == length(Bc) && return nothing + i1 += 1 + c = Bc[i1] end + tz = trailing_zeros(c) + 1 + c = _BLSR(c) + return ((i1-1)<<6 + tz, (i1, c)) end @inline checkbounds(::Type{Bool}, A::AbstractArray, I::LogicalIndex{<:Any,<:AbstractArray{Bool,1}}) = From ada8bc8e9b22469351e0afe5bf9e043a9a9e4381 Mon Sep 17 00:00:00 2001 From: chethega Date: Mon, 22 Oct 2018 19:16:19 +0200 Subject: [PATCH 2/3] changed inbounds / OOB behavior to match array iterators switched spelling of _blsr --- base/bitarray.jl | 2 +- base/multidimensional.jl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 120ce0b5c93fa..aea54aa3385bf 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -84,7 +84,7 @@ IndexStyle(::Type{<:BitArray}) = IndexLinear() const _msk64 = ~UInt64(0) @inline _div64(l) = l >> 6 @inline _mod64(l) = l & 63 -@inline _BLSR(x)= x & (x-1) #zeros the last set bit. Has native instruction on many archs. needed in multidimensional.jl +@inline _blsr(x)= x & (x-1) #zeros the last set bit. Has native instruction on many archs. needed in multidimensional.jl @inline _msk_end(l::Integer) = _msk64 >>> _mod64(-l) @inline _msk_end(B::BitArray) = _msk_end(length(B)) num_bit_chunks(n::Int) = _div64(n+63) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 15b676075b05d..ecfd0cb461628 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -529,16 +529,16 @@ end Bc = L.mask.chunks return iterate(L::Base.LogicalIndex{Int,<:BitArray}, (1, @inbounds Bc[1])) end -@propagate_inbounds function iterate(L::Base.LogicalIndex{Int,<:BitArray}, s) +@inline function iterate(L::Base.LogicalIndex{Int,<:BitArray}, s) Bc = L.mask.chunks i1, c = s while c==0 - i1 == length(Bc) && return nothing + i1 % UInt >= length(Bc) % UInt && return nothing i1 += 1 - c = Bc[i1] + @inbounds c = Bc[i1] end tz = trailing_zeros(c) + 1 - c = _BLSR(c) + c = _blsr(c) return ((i1-1)<<6 + tz, (i1, c)) end From 1328295bb4808f334f7674a2685534b7ac053171 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Wed, 24 Oct 2018 02:18:41 +0200 Subject: [PATCH 3/3] Update base/multidimensional.jl Co-Authored-By: chethega --- base/multidimensional.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index ecfd0cb461628..d79715299fffd 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -527,7 +527,7 @@ end @inline function iterate(L::Base.LogicalIndex{Int,<:BitArray}) L.sum == 0 && return nothing Bc = L.mask.chunks - return iterate(L::Base.LogicalIndex{Int,<:BitArray}, (1, @inbounds Bc[1])) + return iterate(L, (1, @inbounds Bc[1])) end @inline function iterate(L::Base.LogicalIndex{Int,<:BitArray}, s) Bc = L.mask.chunks