Skip to content

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
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information