Какая разница между Array {Bool} и BitArray в Julia и как они связаны?

Я писал функцию для boolean 2d массивов:

function foo(A::Array{Bool,2})
   ...
end

Оценка и тестирование с помощью

A = randbool(3,3)
foo(A)

возвращает

ERROR: 'foo' has no method matching foo(::BitArray{2})

Очевидно, randbool() создает BitArray, тогда как я предположил, что randbool() даст Array{Bool}.

Как связаны Array{Bool} и BitArray? Почему они оба существуют?

Могу ли я написать foo() таким образом, чтобы он принимал оба типа ввода с использованием одного метода (поскольку я не вижу разницы)?

Ответы

Ответ 1

An Array{Bool} хранит каждое значение true/false как Bool, которое представлено внутри UInt8. Поэтому, если ваш массив имеет элементы N, для его хранения потребуется N байтов.

A BitArray хранит каждое значение true/false как один бит, причем (концептуально) 8 из них упакованы в один UInt8. Следовательно, для хранения массива требуется всего N/8 байтов. A BitArray также имеет определенные методы, которые обрабатывают все необходимые операции бит-twiddling для вас.

В зависимости от операции BitArray иногда медленнее, чем соответствующий Array{Bool}, а иногда и быстрее. Но в целом различия в производительности довольно малы, поэтому имеет смысл использовать BitArray, если у вас нет конкретной причины. Но в целом они довольно взаимозаменяемы.

Обратите внимание, что оба являются подтипами AbstractArray{Bool}:

julia> BitArray <: AbstractArray{Bool}
true

julia> Array{Bool} <: AbstractArray{Bool}
true

Это упрощает запись общих методов, которые берут один.