diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 0.4.5
+
+* Addition of `computeIO` and `computePrimM`
+* Addition of `makeArrayLinearA`
+* Addition of `traverseS`
+* Fix regression in performance introduced in `massiv-0.4.0`
+
 # 0.4.4
 
 * Addition of `appendOuterM` and `concatOuterM`
@@ -57,7 +64,7 @@
 * Add an orphan instance of `MonadThrow` for `ST` monad for older versions of
   `exceptions`. See [ekmett/exceptions#72](https://github.com/ekmett/exceptions/pull/72)
 * Deprecation of `read'`, `write'` `modify'` and `swap'`
-* Make `modify` accept a monadic action, rather than a pure function. Also not it returns
+* Make `modify` accept a monadic action, rather than a pure function. Also now it returns
   the old element.
 * Make `swap` return the swapped elements.
 * Addition of `unsafeLinearSwap` and `unsafeSwap`
@@ -130,7 +137,7 @@
 * Addition of `rangeStepInclusive'`
 * Addition of `flatten`
 * `makeLoadArray` has been deprecated into `unsafeMakeLoadArray`.
-* A new safe `makeLoadArrayS` has been aded.
+* A new safe `makeLoadArrayS` has been added.
 * Fix `infix 4` for `(...)` and `(..:)` range functions, so they can be easily composed with
   numeric operations
 * Addition of `imapSchedulerM_` and `iforSchedulerM_`
@@ -231,7 +238,7 @@
 * Addition of `Profunctor` functions for `Stencil`: `lmapStencil`, `rmapStencil` and `bimapStencil`
 * Addition of integration approximation: `Data.Massiv.Array.Numeric.Integral`
 * Removed overlapping instances for `DW` in favor of concrete instances.
-* Relaxed contraint restrictions on matrix multiplication `(|*|)` and slighly improved performance
+* Relaxed contraint restrictions on matrix multiplication `(|*|)` and slightly improved performance
   with rewrite rules to avoid double transform.
 
 # 0.2.2
diff --git a/massiv.cabal b/massiv.cabal
--- a/massiv.cabal
+++ b/massiv.cabal
@@ -1,5 +1,5 @@
 name:                massiv
-version:             0.4.4.0
+version:             0.4.5.0
 synopsis:            Massiv (Массив) is an Array Library.
 description:         Multi-dimensional Arrays with fusion, stencils and parallel computation.
 homepage:            https://github.com/lehins/massiv
diff --git a/src/Data/Massiv/Array.hs b/src/Data/Massiv/Array.hs
--- a/src/Data/Massiv/Array.hs
+++ b/src/Data/Massiv/Array.hs
@@ -84,6 +84,8 @@
   , setComp
   , compute
   , computeS
+  , computeIO
+  , computePrimM
   , computeAs
   , computeProxy
   , computeSource
diff --git a/src/Data/Massiv/Array/Delayed/Stream.hs b/src/Data/Massiv/Array/Delayed/Stream.hs
--- a/src/Data/Massiv/Array/Delayed/Stream.hs
+++ b/src/Data/Massiv/Array/Delayed/Stream.hs
@@ -24,6 +24,7 @@
   , mapMaybeS
   , mapMaybeM
   , catMaybesS
+  , traverseS
   , unfoldr
   , unfoldrN
   ) where
@@ -337,3 +338,11 @@
 dropS :: Stream r ix e => Sz1 -> Array r ix e -> Array DS Ix1 e
 dropS n = fromSteps . S.drop (unSz n) . S.toStream
 {-# INLINE dropS #-}
+
+
+-- | Traverse a stream with an applicative action.
+--
+-- @since 0.4.5
+traverseS :: (S.Stream r ix a, Applicative f) => (a -> f b) -> Array r ix a -> f (Array DS Ix1 b)
+traverseS f = fmap fromSteps . S.traverse f . S.toStream
+{-# INLINE traverseS #-}
diff --git a/src/Data/Massiv/Array/Manifest.hs b/src/Data/Massiv/Array/Manifest.hs
--- a/src/Data/Massiv/Array/Manifest.hs
+++ b/src/Data/Massiv/Array/Manifest.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
diff --git a/src/Data/Massiv/Array/Manifest/Internal.hs b/src/Data/Massiv/Array/Manifest/Internal.hs
--- a/src/Data/Massiv/Array/Manifest/Internal.hs
+++ b/src/Data/Massiv/Array/Manifest/Internal.hs
@@ -23,6 +23,8 @@
   , toManifest
   , compute
   , computeS
+  , computeIO
+  , computePrimM
   , computeAs
   , computeProxy
   , computeSource
@@ -201,13 +203,44 @@
 -- | Ensure that Array is computed, i.e. represented with concrete elements in memory, hence is the
 -- `Mutable` type class restriction. Use `setComp` if you'd like to change computation strategy
 -- before calling @compute@
+--
+-- @since 0.1.0
 compute :: forall r ix e r' . (Mutable r ix e, Load r' ix e) => Array r' ix e -> Array r ix e
-compute !arr = unsafePerformIO $ loadArray arr >>= unsafeFreeze (getComp arr)
+compute !arr = unsafePerformIO $ computeIO arr
 {-# INLINE compute #-}
 
+-- | Compute array sequentially disregarding predefined computation strategy. Very much
+-- the same as `computePrimM`, but executed in `ST`, thus pure.
+--
+-- @since 0.1.0
 computeS :: forall r ix e r' . (Mutable r ix e, Load r' ix e) => Array r' ix e -> Array r ix e
-computeS !arr = runST $ loadArrayS arr >>= unsafeFreeze (getComp arr)
+computeS !arr = runST $ computePrimM arr
 {-# INLINE computeS #-}
+
+-- | Very similar to `compute`, but computes an array inside the `IO` monad. Despite being
+-- deterministic and referentially transparent, because this is an `IO` action it
+-- can be very useful for enforcing the order of evaluation. Should be a prefered way of
+-- computing an array during benchmarking.
+--
+-- @since 0.4.5
+computeIO ::
+     forall r ix e r' m. (Mutable r ix e, Load r' ix e, MonadIO m)
+  => Array r' ix e
+  -> m (Array r ix e)
+computeIO arr = liftIO (loadArray arr >>= unsafeFreeze (getComp arr))
+{-# INLINE computeIO #-}
+
+-- | Compute an array in `PrimMonad` sequentially disregarding predefined computation
+-- strategy.
+--
+-- @since 0.4.5
+computePrimM ::
+     forall r ix e r' m. (Mutable r ix e, Load r' ix e, PrimMonad m)
+  => Array r' ix e
+  -> m (Array r ix e)
+computePrimM arr = loadArrayS arr >>= unsafeFreeze (getComp arr)
+{-# INLINE computePrimM #-}
+
 
 -- | Just as `compute`, but let's you supply resulting representation type as an argument.
 --
diff --git a/src/Data/Massiv/Array/Manifest/Vector/Stream.hs b/src/Data/Massiv/Array/Manifest/Vector/Stream.hs
--- a/src/Data/Massiv/Array/Manifest/Vector/Stream.hs
+++ b/src/Data/Massiv/Array/Manifest/Vector/Stream.hs
@@ -86,8 +86,6 @@
 import Prelude hiding (zipWith, mapM, traverse, length, foldl, foldr, filter, concatMap, drop, take)
 
 
-
-
 -- TODO: benchmark: `fmap snd . isteps`
 steps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m e
 steps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
diff --git a/src/Data/Massiv/Array/Ops/Construct.hs b/src/Data/Massiv/Array/Ops/Construct.hs
--- a/src/Data/Massiv/Array/Ops/Construct.hs
+++ b/src/Data/Massiv/Array/Ops/Construct.hs
@@ -43,6 +43,7 @@
     -- *** Applicative
   , makeArrayA
   , makeArrayAR
+  , makeArrayLinearA
     -- ** Enumeration
   , (...)
   , (..:)
@@ -133,7 +134,6 @@
 --
 --
 -- @since 0.2.6
---
 makeArrayA ::
      forall r ix e f. (Mutable r ix e, Applicative f)
   => Sz ix
@@ -151,11 +151,27 @@
    in runSTA sz <$> go 0
 {-# INLINE makeArrayA  #-}
 
+-- | Same as `makeArrayA`, but with linear index.
+--
+-- @since 0.4.5
+makeArrayLinearA ::
+     forall r ix e f. (Mutable r ix e, Applicative f)
+  => Sz ix
+  -> (Int -> f e)
+  -> f (Array r ix e)
+makeArrayLinearA !sz f =
+  let n = totalElem sz
+      go !i
+        | i < n =
+          liftA2 (\e (STA st) -> STA (\ma -> unsafeLinearWrite ma i e >> st ma)) (f i) (go (i + 1))
+        | otherwise = pure (STA (unsafeFreeze Seq))
+   in runSTA sz <$> go 0
+{-# INLINE makeArrayLinearA  #-}
 
+
 -- | Same as `makeArrayA`, but with ability to supply result array representation.
 --
 -- @since 0.2.6
---
 makeArrayAR ::
      forall r ix e f. (Mutable r ix e, Applicative f)
   => r
@@ -290,7 +306,7 @@
   => g -- ^ Initial random value generator
   -> (g -> (g, g))
      -- ^ A function that can split a generator in two independent generators
-  -> (g -> (e, g)) -- TODO: move this argument after the sz, to keep ot consistent.
+  -> (g -> (e, g))
      -- ^ A function that produces a random value and the next generator
   -> Comp -- ^ Computation strategy.
   -> Sz ix -- ^ Resulting size of the array.
diff --git a/src/Data/Massiv/Array/Ops/Map.hs b/src/Data/Massiv/Array/Ops/Map.hs
--- a/src/Data/Massiv/Array/Ops/Map.hs
+++ b/src/Data/Massiv/Array/Ops/Map.hs
@@ -23,6 +23,7 @@
   , itraverseAR
   , sequenceA
   , sequenceA_
+  , traverseS
   -- *** PrimMonad
   , traversePrim
   , itraversePrim
@@ -79,8 +80,9 @@
 import Control.Scheduler
 import Data.Coerce
 import Data.Massiv.Array.Delayed.Pull
+import Data.Massiv.Array.Delayed.Stream
 import Data.Massiv.Array.Mutable
-import Data.Massiv.Array.Ops.Construct (makeArrayA)
+import Data.Massiv.Array.Ops.Construct (makeArrayA, makeArrayLinearA)
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.Index.Internal (Sz(..))
 import Prelude hiding (map, mapM, mapM_, sequenceA, traverse, unzip, unzip3,
@@ -276,7 +278,7 @@
   => (a -> f e)
   -> Array r' ix a
   -> f (Array r ix e)
-traverseA f arr = setComp (getComp arr) <$> makeArrayA (size arr) (f . unsafeIndex arr)
+traverseA f arr = makeArrayLinearA (size arr) (f . unsafeLinearIndex arr)
 {-# INLINE traverseA #-}
 
 -- | Traverse sequentially over a source array, while discarding the result.
diff --git a/src/Data/Massiv/Array/Stencil.hs b/src/Data/Massiv/Array/Stencil.hs
--- a/src/Data/Massiv/Array/Stencil.hs
+++ b/src/Data/Massiv/Array/Stencil.hs
@@ -343,7 +343,7 @@
 --
 -- ==== __Example__
 --
--- Here is a sample implementation of min pooling.
+-- Here is a sample implementation of max pooling.
 --
 -- >>> import Data.Massiv.Array as A
 -- >>> a <- computeAs P <$> resizeM (Sz2 9 9) (Ix1 10 ..: 91)
diff --git a/src/Data/Massiv/Core/Index/Internal.hs b/src/Data/Massiv/Core/Index/Internal.hs
--- a/src/Data/Massiv/Core/Index/Internal.hs
+++ b/src/Data/Massiv/Core/Index/Internal.hs
@@ -1,18 +1,18 @@
-{-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DefaultSignatures #-}
-{-# LANGUAGE ExplicitNamespaces #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}
 #if __GLASGOW_HASKELL__ < 820
 {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
@@ -346,7 +346,7 @@
 -- safely used with it.
 --
 -- @since 0.2.4
-type IsIndexDimension ix n = (IsDimValid ix n ~ 'True, Index ix, KnownNat n)
+type IsIndexDimension ix n = (1 <= n, n <= Dimensions ix, Index ix, KnownNat n)
 
 
 -- | This type family will always point to a type for a dimension that is one lower than the type
@@ -378,7 +378,6 @@
       , Ord (Lower ix)
       , Show (Lower ix)
       , NFData (Lower ix)
-      , 1 <= Dimensions ix
       , KnownNat (Dimensions ix)
       ) =>
       Index ix
