I'd like to use @inbounds also to speed up code that I'm 100% sure has
proper array indices. But I tried the following experiment and found no
significant difference using or omitting @inbounds before the array access.
What am I doing wrong? Or is bounds checking so super efficient that I
shouldn't worry about it.
Here's the code:
function filler(data::Array{Int,1}, n::Int, reps::Int=1000)
tic()
for r=1:reps
for k=1:n
data[k]=k
end
end
toc()
end
function fast_filler(data::Array{Int,1},n::Int, reps::Int=1000)
tic()
for r=1:reps
for k=1:n
@inbounds data[k]=k
end
end
toc()
end
n = 10*1000*1000 # 10 million
x = zeros(Int,n)
filler(x,n,1000)
fast_filler(x,n,1000)
Here's the output:
elapsed time: 12.622814907 seconds
elapsed time: 12.287447772 seconds
On Monday, August 4, 2014 1:56:51 PM UTC-4, Jacob Quinn wrote:
>
> Steve,
>
> `@inbounds` is certainly tricky because of the lack of documentation,
> which I think is slightly on purpose as this is meant to be for more
> advanced usage.
>
> The main insight to using `@inbounds` correctly is realizing that
> `@inbounds expression` returns the value `nothing`. That's why your first
> two examples don't seem to work. The value is indeed being calculated with
> bounds checking off, but you're not assigning the value anywhere, so
> `nothing` is the result of the expression. You can also do multi-line
> turning off of bounds checking by using a `begin...end` block.
>
> Try the following:
>
> function sqrtfirst{T}(a::Array{T, 1})
> @assert(size(a,1) >= 1)
> @inbounds ans = sqrt(a[1])
> return ans
> end
>
> function sqrtfirst{T}(a::Array{T, 1})
> @assert(size(a,1) >= 1)
> @inbounds begin
> # do several getindex, setindex! operations
> end
> return ans
> end
>
> Hope that helps!
>
> -Jacob
>
>
> On Mon, Aug 4, 2014 at 1:45 PM, <[email protected] <javascript:>> wrote:
>
>> Dear Julia users,
>>
>> The usage of the @inbounds macro is not explained the manual, and its
>> syntax appears to be strange. Consider the three functions at the end of
>> this posting. Only the third one works -- why?
>>
>> In general, I think @inbounds is broken. Besides the weird syntax, it
>> has two other issues. First, there is no way to apply the macro to one
>> subscript operation but not another in a long expression (as far as I
>> know). Second, it is not extensible in the sense that if programmer A
>> implements his/her own array-like structure with his/her own getindex and
>> setindex operations, he/she might like to have two versions of
>> getindex/setindex, one safe/slower and the other unsafe/faster, but there
>> is no way for programmer A to detect whether user B, a user of his/her new
>> array-like structure, has requested @inbounds or not.
>>
>> I would like to propose the following replacement for @inbounds, which
>> solves all three problems. Instead of a macro, there should be two
>> different subscript operations, say a[1] and a[$ 1 $], where the first is
>> safe/slow and the second is unsafe/fast. The compiler will compile the
>> first as getindex/setindex and the second as getindexUnsafe/setindexUnsafe.
>>
>> -- Steve Vavasis
>>
>>
>>
>> function sqrtfirst{T}(a::Array{T, 1})
>> @assert(size(a,1) >= 1)
>> @inbounds sqrt(a[1])
>> end
>>
>> function sqrtfirst{T}(a::Array{T, 1})
>> @assert(size(a,1) >= 1)
>> return @inbounds sqrt(a[1])
>> end
>>
>> function sqrtfirst{T}(a::Array{T, 1})
>> @assert(size(a,1) >= 1)
>> @inbounds return sqrt(a[1])
>> end
>>
>>
>>
>>
>