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 |