From 15ba7e299b333b63e349268a832ad369c62167fd Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 23 Sep 2009 01:05:19 -0500 Subject: [PATCH] math.vectors.simd: fix all tests --- basis/math/vectors/simd/simd-docs.factor | 28 ++++------- basis/math/vectors/simd/simd-tests.factor | 60 +++++++++++++++-------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/basis/math/vectors/simd/simd-docs.factor b/basis/math/vectors/simd/simd-docs.factor index ef625ffff0..6d212f8e2b 100644 --- a/basis/math/vectors/simd/simd-docs.factor +++ b/basis/math/vectors/simd/simd-docs.factor @@ -1,5 +1,5 @@ -USING: help.markup help.syntax sequences math math.vectors -multiline kernel.private classes.tuple.private +USING: help.markup help.syntax help.vocabs sequences math +math.vectors multiline kernel.private classes.tuple.private math.vectors.simd.intrinsics cpu.architecture ; IN: math.vectors.simd @@ -159,22 +159,8 @@ ARTICLE: "math.vectors.simd.intrinsics" "Low-level SIMD primitives" } "The compiler converts " { $link "math-vectors" } " into SIMD primitives automatically in cases where it is safe; this means that the input types are known to be SIMD vectors, and the CPU supports SIMD." $nl -"It is best to avoid calling these primitives directly. To write efficient high-level code that compiles down to primitives and avoids memory allocation, see " { $link "math.vectors.simd.efficiency" } "." -{ $subsection (simd-v+) } -{ $subsection (simd-vs+) } -{ $subsection (simd-v+-) } -{ $subsection (simd-v-) } -{ $subsection (simd-vs-) } -{ $subsection (simd-v*) } -{ $subsection (simd-vs*) } -{ $subsection (simd-v/) } -{ $subsection (simd-vmin) } -{ $subsection (simd-vmax) } -{ $subsection (simd-vsqrt) } -{ $subsection (simd-sum) } -{ $subsection (simd-broadcast) } -{ $subsection (simd-gather-2) } -{ $subsection (simd-gather-4) } +"It is best to avoid calling SIMD primitives directly. To write efficient high-level code that compiles down to primitives and avoids memory allocation, see " { $link "math.vectors.simd.efficiency" } "." +$nl "There are two primitives which are used to implement accessing SIMD vector fields of " { $link "classes.struct" } ":" { $subsection alien-vector } { $subsection set-alien-vector } @@ -185,12 +171,18 @@ ARTICLE: "math.vectors.simd.alien" "SIMD data in struct classes" $nl "Only SIMD struct fields are allowed at the moment; passing SIMD data as function parameters is not yet supported." ; +ARTICLE: "math.vectors.simd.accuracy" "Numerical accuracy of SIMD primitives" +"No guarantees are made that " { $vocab-link "math.vectors.simd" } " words will give identical results on different SSE versions, or between the hardware intrinsics and the software fallbacks." +$nl +"In particular, horizontal operations on " { $snippet "float-4" } " and " { $snippet "float-8" } " are affected by this. They are computed with lower precision in intrinsics than the software fallback. Horizontal opeartions include anything involving adding together the components of a vector, such as " { $link sum } " or " { $link normalize } "." ; + ARTICLE: "math.vectors.simd" "Hardware vector arithmetic (SIMD)" "The " { $vocab-link "math.vectors.simd" } " vocabulary extends the " { $vocab-link "math.vectors" } " vocabulary to support efficient vector arithmetic on small, fixed-size vectors." { $subsection "math.vectors.simd.intro" } { $subsection "math.vectors.simd.types" } { $subsection "math.vectors.simd.words" } { $subsection "math.vectors.simd.support" } +{ $subsection "math.vectors.simd.accuracy" } { $subsection "math.vectors.simd.efficiency" } { $subsection "math.vectors.simd.alien" } { $subsection "math.vectors.simd.intrinsics" } ; diff --git a/basis/math/vectors/simd/simd-tests.factor b/basis/math/vectors/simd/simd-tests.factor index 39afe3cb03..007ec338cd 100644 --- a/basis/math/vectors/simd/simd-tests.factor +++ b/basis/math/vectors/simd/simd-tests.factor @@ -74,17 +74,18 @@ CONSTANT: simd-classes : boa-ctors ( -- seq ) simd-classes [ [ name>> "-boa" append ] [ vocabulary>> ] bi lookup ] map ; -: check-optimizer ( seq inputs quot -- ) - [ +: check-optimizer ( seq inputs quot eq-quot -- ) + '[ + @ [ "print-mr" get [ nip test-mr mr. ] [ 2drop ] if ] [ [ call ] dip call ] - [ [ call ] dip compile-call ] 2tri = not - ] compose filter ; inline + [ [ call ] dip compile-call ] 2tri @ not + ] filter ; inline "== Checking -new constructors" print [ { } ] [ - simd-classes [ [ [ ] ] dip '[ _ new ] ] check-optimizer + simd-classes [ [ [ ] ] dip '[ _ new ] ] [ = ] check-optimizer ] unit-test [ { } ] [ @@ -96,7 +97,7 @@ CONSTANT: simd-classes [ { } ] [ with-ctors [ [ 1000 random '[ _ ] ] dip '[ { fixnum } declare _ execute ] - ] check-optimizer + ] [ = ] check-optimizer ] unit-test "== Checking -boa constructors" print @@ -107,7 +108,7 @@ CONSTANT: simd-classes [ nip [ 1000 random ] [ ] replicate-as ] [ fixnum swap '[ _ declare _ execute ] ] 2bi - ] check-optimizer + ] [ = ] check-optimizer ] unit-test "== Checking vector operations" print @@ -133,24 +134,44 @@ CONSTANT: simd-classes ] bi word '[ _ declare _ execute ] ; -: ops-to-check ( elt-class -- alist ) - [ vector-words >alist ] dip float = [ - [ drop { n/v v/n v/ normalize } member? not ] assoc-filter - ] unless ; +: remove-float-words ( alist -- alist' ) + [ drop { n/v v/n v/ normalize } member? not ] assoc-filter ; -: check-vector-ops ( class elt-class -- ) - [ nip ops-to-check ] 2keep - '[ first2 inputs _ _ check-vector-op ] check-optimizer ; inline +: ops-to-check ( elt-class -- alist ) + [ vector-words >alist ] dip + float = [ remove-float-words ] unless ; + +: check-vector-ops ( class elt-class compare-quot -- ) + [ + [ nip ops-to-check ] 2keep + '[ first2 inputs _ _ check-vector-op ] + ] dip check-optimizer ; inline + +: approx= ( x y -- ? ) + { + { [ 2dup [ float? ] both? ] [ -1.e8 ~ ] } + { [ 2dup [ sequence? ] both? ] [ + [ + { + { [ 2dup [ fp-nan? ] both? ] [ 2drop t ] } + { [ 2dup [ fp-nan? ] either? not ] [ -1.e8 ~ ] } + } cond + ] 2all? + ] } + } cond ; : simd-classes&reps ( -- alist ) simd-classes [ - dup name>> [ "float" head? ] [ "double" head? ] bi or - float fixnum ? - ] { } map>assoc ; + { + { [ dup name>> "float" head? ] [ float [ approx= ] ] } + { [ dup name>> "double" tail? ] [ float [ = ] ] } + [ fixnum [ = ] ] + } cond 3array + ] map ; simd-classes&reps [ - [ [ { } ] ] 2dip '[ _ _ check-vector-ops ] unit-test -] assoc-each + [ [ { } ] ] dip first3 '[ _ _ _ check-vector-ops ] unit-test +] each ! Other regressions [ 8000000 ] [ @@ -158,7 +179,6 @@ simd-classes&reps [ [ { int-8 } declare dup [ * ] [ + ] 2map-reduce ] compile-call ] unit-test - ! Vector alien intrinsics [ float-4{ 1 2 3 4 } ] [ [