index variable for array traversal worker function is not unboxed
See also http://hackage.haskell.org/trac/ghc/ticket/3606.
In an attempt to write a better comparison function for unboxed arrays, I wrote the following code:
{-# LANGUAGE BangPatterns #-}
{-# OPTIONS -Wall #-}
module BadArrayCmp where
import Data.Array.Base
import Data.Array.Unboxed
cmpArrays :: (IArray a1 e, IArray a2 e, Ix i, Ord e)
=> a1 i e
-> a2 i e
-> Ordering
cmpArrays a1 a2 = case compare (bounds a1) (bounds a2) of
LT -> LT
EQ -> go 0
GT -> GT
where
iMaxPlusOne :: Int
iMaxPlusOne = numElements a1
go :: Int -> Ordering
go !i = if i == iMaxPlusOne
then EQ
else case compare (unsafeAt a1 i) (unsafeAt a2 i) of
LT -> LT
EQ -> go (i+1)
GT -> GT
{-# INLINE cmpArrays #-}
I have attached this code as a test case.
Examining the core generated by ghc 6.10.4 using -O2 on Ubuntu 9.04 x86_64, the code generated for 'go' uses a boxed Int for the index variable.
Because of this boxed int (and perhaps other problems in the generated code, I'm not sure), in a particular application of mine, ~60% of the total time is used and %80% of the total allocation is done in 'cmpArrays'. (These percentages obtained via profiling.)
I imagine that 'go' could be compiled so that the only potential allocation done is for the Ordering value at the end. Using a boxed index variable instead of something kept in a register really kills performance!
Trac metadata
Trac field | Value |
---|---|
Version | 6.10.4 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |