Given the performance difference and the different behavior, I'm tempted to just deprecate the two-argument form of pointer.
On Wed, Mar 25, 2015 at 12:53 PM, Sebastian Good < [email protected]> wrote: > I guess what I find most confusing is that there would be a difference, > since adding 1 to a pointer only adds one byte, not one element size. > > > p1 = pointer(zeros(UInt64)); > Ptr{UInt64} @0x000000010b28c360 > > p1 + 1 > Ptr{UInt64} @0x000000010b28c361 > > I would have expected the latter to end in 68. the two argument pointer > function gets this “right”. > > > a=zeros(UInt64); > > pointer(a,1) > Ptr{Int64} @0x000000010b9c72e0 > > pointer(a,2) > Ptr{Int64} @0x000000010b9c72e8 > > I can see arguments multiple ways, but when I’m given a strongly typed > pointer (Ptr{T}), I would expect it to participate in arithmetic in > increments of sizeof(T). > > On March 25, 2015 at 6:36:37 AM, Stefan Karpinski ([email protected]) > wrote: > > That does seem to be the issue. It's tricky to fix since you can't > evaluate sizeof(Ptr) unless the condition is true. > > On Tue, Mar 24, 2015 at 7:13 PM, Stefan Karpinski <[email protected]> > wrote: > >> There's a branch in eltype, which is probably causing this difference. >> >> On Tue, Mar 24, 2015 at 7:00 PM, Sebastian Good < >> [email protected]> wrote: >> >>> Yep, that’s done it. The only difference I can see in the code I wrote >>> before and this code is that previously I had >>> >>> convert(Ptr{T}, pointer(raw, byte_number)) >>> >>> whereas here we have >>> >>> convert(Ptr{T}, pointer(raw) + byte_number - 1) >>> >>> The former construction seems to emit a call to a Julia-intrinsic >>> function, while the latter executes the more expected simple machine loads. >>> Is there a subtle difference between the two calls to pointer? >>> >>> Thanks all for your help! >>> >>> On March 24, 2015 at 12:19:00 PM, Matt Bauman ([email protected]) wrote: >>> >>> (The key is to ensure that the method gets specialized for different >>> types with the parametric `::Type{T}` in the signature instead of >>> `T::DataType`). >>> >>> On Tuesday, March 24, 2015 at 12:10:59 PM UTC-4, Stefan Karpinski wrote: >>>> >>>> This seems like it works fine to me (on both 0.3 and 0.4): >>>> >>>> immutable Test >>>> x::Float32 >>>> y::Int64 >>>> z::Int8 >>>> end >>>> >>>> julia> a = [Test(1,2,3)] >>>> 1-element Array{Test,1}: >>>> Test(1.0f0,2,3) >>>> >>>> julia> b = copy(reinterpret(UInt8, a)) >>>> 24-element Array{UInt8,1}: >>>> 0x00 >>>> 0x00 >>>> 0x80 >>>> 0x3f >>>> 0x03 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> 0x02 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> 0x03 >>>> 0xe0 >>>> 0x82 >>>> 0x10 >>>> 0x01 >>>> 0x00 >>>> 0x00 >>>> 0x00 >>>> >>>> julia> prim_read{T}(::Type{T}, data::Array{Uint8,1}, offset::Int) = >>>> unsafe_load(convert(Ptr{T}, pointer(data) + offset)) >>>> prim_read (generic function with 1 method) >>>> >>>> julia> prim_read(Test, b, 0) >>>> Test(1.0f0,2,3) >>>> >>>> julia> @code_native prim_read(Test, b, 0) >>>> .section __TEXT,__text,regular,pure_instructions >>>> Filename: none >>>> Source line: 1 >>>> push RBP >>>> mov RBP, RSP >>>> Source line: 1 >>>> mov RCX, QWORD PTR [RSI + 8] >>>> vmovss XMM0, DWORD PTR [RCX + RDX] >>>> mov RAX, QWORD PTR [RCX + RDX + 8] >>>> mov DL, BYTE PTR [RCX + RDX + 16] >>>> pop RBP >>>> ret >>>> >>>> >>>> On Tue, Mar 24, 2015 at 5:04 PM, Simon Danisch <[email protected]> >>>> wrote: >>>> >>>>> There is a high chance that I simply don't understand llvmcall well >>>>> enough, though ;) >>>>> >>>>> Am Montag, 23. März 2015 20:20:09 UTC+1 schrieb Sebastian Good: >>>>>> >>>>>> I'm trying to read some binary formatted data. In C, I would define >>>>>> an appropriately padded struct and cast away. Is is possible to do >>>>>> something similar in Julia, though for only one value at a time? >>>>>> Philosophically, I'd like to approximate the following, for some simple >>>>>> bittypes T (Int32, Float32, etc.) >>>>>> >>>>>> T read<T>(char* data, size_t offset) { return *(T*)(data + offset); } >>>>>> >>>>>> The transliteration of this brain-dead approach results in the >>>>>> following, which seems to allocate a boxed Pointer object on every >>>>>> invocation. The pointer function comes with ample warnings about how it >>>>>> shouldn't be used, and I imagine that it's not polite to the garbage >>>>>> collector. >>>>>> >>>>>> prim_read{T}(::Type{T}, data::AbstractArray{Uint8, 1}, byte_number) >>>>>> = unsafe_load(convert(Ptr{T}, pointer(data, byte_number))) >>>>>> >>>>>> I can reinterpret the whole array, but this will involve a division >>>>>> of the offset to calculate the new offset relative to the reinterpreted >>>>>> array, and it allocates an array object. >>>>>> >>>>>> Is there a better way to simply read the machine word at a particular >>>>>> offset in a byte array? I would think it should inline to a single >>>>>> assembly >>>>>> instruction if done right. >>>>>> >>>>>> >>>>> >>>> >> >
