diff --git a/include/bolt/amp/detail/transform.inl b/include/bolt/amp/detail/transform.inl index 6de22b47..d9742f5e 100644 --- a/include/bolt/amp/detail/transform.inl +++ b/include/bolt/amp/detail/transform.inl @@ -33,6 +33,7 @@ #include #include "bolt/amp/bolt.h" #include "bolt/amp/device_vector.h" +#include "bolt/amp/iterator/iterator_traits.h" #ifdef ENABLE_TBB #include "bolt/btbb/transform.h" @@ -61,34 +62,45 @@ namespace bolt typedef std::iterator_traits< DVInputIterator2 >::value_type iType2; typedef std::iterator_traits< DVOutputIterator >::value_type oType; + typedef std::iterator_traits< DVInputIterator1 >::pointer container_type; + + typedef concurrency::array_view array_view_type1; + typedef concurrency::array_view array_view_type2; + typedef bolt::amp::constant_iterator constant_iter_type1; + typedef bolt::amp::constant_iterator constant_iter_type2; + + const unsigned int arraySize = static_cast< unsigned int >( std::distance( first1, last1 ) ); unsigned int wavefrontMultiple = arraySize; const unsigned int lowerBits = ( arraySize & ( WAVEFRNT_SIZE -1 ) ); - int boundsCheck = 0; + int boundsCheck = 0; if( lowerBits ) { wavefrontMultiple &= ~lowerBits; wavefrontMultiple += WAVEFRNT_SIZE; - } - else - boundsCheck = 1; + } + else + { + boundsCheck = 1; + } - concurrency::array_view inputV1 (first1.getContainer().getBuffer(first1)); - concurrency::array_view inputV2 (first2.getContainer().getBuffer(first2)); - concurrency::array_view resultV(result.getContainer().getBuffer(result)); + auto inputV1 = first1.getContainer().getBuffer(first1); + auto inputV2 = first2.getContainer().getBuffer(first2); + auto resultV = result.getContainer().getBuffer(result); concurrency::extent< 1 > inputExtent( wavefrontMultiple ); concurrency::parallel_for_each(ctl.getAccelerator().default_view, inputExtent, [=](concurrency::index<1> idx) restrict(amp) { unsigned int globalId = idx[0]; - if(boundsCheck == 0) - { - if( globalId >= arraySize ) - return; - } + if(boundsCheck == 0) + { + if( globalId >= arraySize ) + return; + } resultV[idx[0]] = f(inputV1[globalId], inputV2[globalId]); + }); }; @@ -117,8 +129,8 @@ namespace bolt else boundsCheck = 1; - concurrency::array_view inputV (first.getContainer().getBuffer(first)); - concurrency::array_view resultV(result.getContainer().getBuffer(result)); + auto inputV = first.getContainer().getBuffer(first); + auto resultV = result.getContainer().getBuffer(result); concurrency::extent< 1 > inputExtent( wavefrontMultiple ); concurrency::parallel_for_each(ctl.getAccelerator().default_view, inputExtent, [=](concurrency::index<1> idx) restrict(amp) @@ -139,6 +151,51 @@ namespace bolt \detail This template is called by the non-detail versions of transform, it already assumes random access * iterators. This overload is called strictly for non-device_vector iterators */ + + template + void transform_pick_iterator(bolt::amp::control &ctl, + const InputIterator1& first1, + const InputIterator1& last1, + const InputIterator2& first2, + const OutputIterator& result, + const BinaryFunction& f, bolt::amp::fancy_iterator_tag) + { + typedef std::iterator_traits::value_type iType1; + typedef std::iterator_traits::value_type iType2; + typedef std::iterator_traits::value_type oType; + size_t sz = (last1 - first1); + if (sz == 0) + return; + // Use host pointers memory since these arrays are only read once - no benefit to copying. + const bolt::amp::control::e_RunMode runMode = ctl.getForceRunMode(); // could be dynamic choice some day. + if (runMode == bolt::amp::control::SerialCpu) + { + std::transform(first1, last1, first2, result, f); + return; + } + else if (runMode == bolt::amp::control::MultiCoreCpu) + { +#if defined( ENABLE_TBB ) + + bolt::btbb::transform(first1, last1, first2, result, f); +#else + throw std::exception("The MultiCoreCpu version of transform is not enabled to be built."); +#endif + return; + } + else + { + // Use host pointers memory since these arrays are only read once - no benefit to copying. + // Map the input iterator to a device_vector + device_vector< iType2, concurrency::array_view > dvInput2(first2, sz, false, ctl); + // Map the output iterator to a device_vector + device_vector< oType, concurrency::array_view > dvOutput(result, sz, true, ctl); + transform_enqueue(ctl, first1, last1, dvInput2.begin(), dvOutput.begin(), f); + // This should immediately map/unmap the buffer + dvOutput.data(); + } + } + template typename std::enable_if< !(std::is_base_of::value_type>::iterator,InputIterator1>::value && @@ -150,7 +207,8 @@ namespace bolt const InputIterator1& last1, const InputIterator2& first2, const OutputIterator& result, - const BinaryFunction& f) + const BinaryFunction& f, + std::random_access_iterator_tag) { typedef std::iterator_traits::value_type iType1; typedef std::iterator_traits::value_type iType2; @@ -205,7 +263,8 @@ namespace bolt const DVInputIterator1& last1, const DVInputIterator2& first2, const DVOutputIterator& result, - const BinaryFunction& f ) + const BinaryFunction& f, + bolt::amp::device_vector_tag) { typedef std::iterator_traits< DVInputIterator1 >::value_type iType1; typedef std::iterator_traits< DVInputIterator2 >::value_type iType2; @@ -265,7 +324,8 @@ namespace bolt const InputIterator& first, const InputIterator& last, const OutputIterator& result, - const UnaryFunction& f) + const UnaryFunction& f, + std::random_access_iterator_tag) { typedef std::iterator_traits::value_type iType; typedef std::iterator_traits::value_type oType; @@ -319,7 +379,8 @@ namespace bolt const DVInputIterator& first, const DVInputIterator& last, const DVOutputIterator& result, - const UnaryFunction& f ) + const UnaryFunction& f, + bolt::amp::device_vector_tag) { typedef std::iterator_traits< DVInputIterator >::value_type iType; @@ -365,6 +426,47 @@ namespace bolt } }; + template + void transform_unary_pick_iterator( bolt::amp::control &ctl, + const DVInputIterator& first, + const DVInputIterator& last, + const DVOutputIterator& result, + const UnaryFunction& f, + bolt::amp::fancy_iterator_tag) + { + + typedef std::iterator_traits< DVInputIterator >::value_type iType; + typedef std::iterator_traits< DVOutputIterator >::value_type oType; + + size_t sz = std::distance( first, last ); + if( sz == 0 ) + return; + + const bolt::amp::control::e_RunMode runMode = ctl.getForceRunMode(); // could be dynamic choice some day. + + // TBB does not have an equivalent for two input iterator std::transform + if( (runMode == bolt::amp::control::SerialCpu) ) + { + std::transform( first, last, result, f ); + return; + } + else if( (runMode == bolt::amp::control::MultiCoreCpu) ) + { + +#if defined( ENABLE_TBB ) + + bolt::btbb::transform( first, last, result, f); +#else + throw std::exception( "The MultiCoreCpu version of transform is not enabled to be built." ); +#endif + return; + } + else + { + transform_unary_enqueue( ctl, first, last, result, f); + } + }; + // Wrapper that uses default control class, iterator interface template @@ -425,7 +527,20 @@ namespace bolt std::random_access_iterator_tag, std::random_access_iterator_tag) { - transform_pick_iterator( ctl, first1, last1, first2, result, f ); + transform_pick_iterator( ctl, first1, last1, first2, result, f, std::iterator_traits< InputIterator1 >::iterator_category() ); + } + + template + void transform_detect_random_access(bolt::amp::control& ctl, + const InputIterator1& first1, + const InputIterator1& last1, + const InputIterator2& first2, + const OutputIterator& result, + const BinaryFunction& f, + bolt::amp::fancy_iterator_tag, + std::random_access_iterator_tag) + { + transform_pick_iterator(ctl, first1, last1, first2, result, f, std::iterator_traits< InputIterator1 >::iterator_category()); } // Wrapper that uses default control class, iterator interface @@ -450,7 +565,18 @@ namespace bolt const UnaryFunction& f, std::random_access_iterator_tag ) { - transform_unary_pick_iterator( ctl, first1, last1, result, f ); + transform_unary_pick_iterator( ctl, first1, last1, result, f, std::iterator_traits< InputIterator >::iterator_category() ); + } + + template + void transform_unary_detect_random_access( bolt::amp::control& ctl, + const InputIterator& first1, + const InputIterator& last1, + const OutputIterator& result, + const UnaryFunction& f, + bolt::amp::fancy_iterator_tag ) + { + transform_unary_pick_iterator( ctl, first1, last1, result, f, std::iterator_traits< InputIterator >::iterator_category() ); } diff --git a/include/bolt/amp/iterator/constant_iterator.h b/include/bolt/amp/iterator/constant_iterator.h new file mode 100644 index 00000000..cce2ff9a --- /dev/null +++ b/include/bolt/amp/iterator/constant_iterator.h @@ -0,0 +1,254 @@ +/*************************************************************************** +* Copyright 2012 - 2013 Advanced Micro Devices, Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + +***************************************************************************/ +#pragma once +#if !defined( BOLT_CL_CONSTANT_ITERATOR_H ) +#define BOLT_CL_CONSTANT_ITERATOR_H +#include "bolt/amp/bolt.h" +#include "bolt/amp/iterator/iterator_traits.h" +#include + +/*! \file bolt/cl/iterator/constant_iterator.h + \brief Return Same Value or Constant Value on dereferencing. +*/ + + +namespace bolt { +namespace amp { + + struct constant_iterator_tag + : public fancy_iterator_tag + { // identifying tag for random-access iterators + }; + + template< typename value_type > + class constant_iterator: public std::iterator< constant_iterator_tag, typename value_type, int> + { + public: + //typedef typename std::iterator< constant_iterator< value_type >, value_type, + //constant_iterator_tag, value_type, int >::difference_type difference_type; + typedef int difference_type; + + typedef concurrency::array_view< value_type > arrayview_type; + typedef constant_iterator const_iterator; + typedef + + + struct Payload + { + value_type m_Value; + }; + + // Basic constructor requires a reference to the container and a positional element + constant_iterator( value_type init, const control& ctl = control::getDefault( ) ): + m_constValue( init ), m_Index( 0 ){} + + // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa + template< typename OtherType > + constant_iterator( const constant_iterator< OtherType >& rhs ): m_devMemory( rhs.m_devMemory ), + m_Index( rhs.m_Index ), m_constValue( rhs.m_constValue ){} + + // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa + constant_iterator< value_type >& operator= ( const constant_iterator< value_type >& rhs ) + { + if( this == &rhs ) + return *this; + + m_constValue = rhs.m_constValue; + m_Index = rhs.m_Index; + return *this; + } + + constant_iterator< value_type >& operator+= ( const difference_type & n ) + { + advance( n ); + return *this; + } + + const constant_iterator< value_type > operator+ ( const difference_type & n ) const + { + constant_iterator< value_type > result( *this ); + result.advance( n ); + return result; + } + + arrayview_type getBuffer() const + { + } + + //arrayview_type getBuffer(const_iterator itr) const + //{ + // //difference_type offset = 1;//itr.getIndex(); + // //concurrency::extent<1> ext( static_cast< int >( 1 /*m_Size-offset*/ )); + // //return m_devMemory->section( Concurrency::index<1>((int)1), ext ); + // + + // ////return m_devMemory->reinterpret_as(); + // return m_constValue; + // + //} + + + + //int getBuffer(const_iterator itr) const + //{ + // //difference_type offset = 1;//itr.getIndex(); + // //concurrency::extent<1> ext( static_cast< int >( 1 /*m_Size-offset*/ )); + // //return m_devMemory->section( Concurrency::index<1>((int)1), ext ); + // + // return m_constValue; + // + //} + + const constant_iterator< value_type > & getBuffer( const_iterator itr ) const + { + return *this; + } + + + const constant_iterator< value_type > & getContainer( ) const + { + return *this; + } + + //Payload gpuPayload( ) const + //{ + // Payload payload = { m_constValue }; + // return payload; + //} + + //const difference_type gpuPayloadSize( ) const + //{ + // return sizeof( Payload ); + //} + + difference_type operator- ( const constant_iterator< value_type >& rhs ) const + { + //return static_cast< typename iterator_facade::difference_type >( 1 ); + return m_Index - rhs.m_Index; + } + + // Public member variables + difference_type m_Index; + + //private: + + // Used for templatized copy constructor and the templatized equal operator + template < typename > friend class constant_iterator; + + // For a constant_iterator, do nothing on an advance + void advance( difference_type n ) + { + m_Index += n; + } + + void operator++( ) + { + advance( 1 ); + } + + void operator--( ) + { + advance( -1 ); + } + + difference_type getIndex() const + { + return m_Index; + } + + //template< typename OtherType > + //bool equal( const constant_iterator< OtherType >& rhs ) const + //{ + // bool sameIndex = (rhs.m_constValue == m_constValue) && (rhs.m_Index == m_Index); + + // return sameIndex; + //} + + template< typename OtherType > + bool operator== ( const constant_iterator< OtherType >& rhs ) const + { + bool sameIndex = (rhs.m_constValue == m_constValue) && (rhs.m_Index == m_Index); + + return sameIndex; + } + + template< typename OtherType > + bool operator!= ( const constant_iterator< OtherType >& rhs ) const + { + bool sameIndex = (rhs.m_constValue != m_constValue) || (rhs.m_Index != m_Index); + + return sameIndex; + } + + // Do we need this? Debug error + template< typename OtherType > + bool operator< ( const constant_iterator< OtherType >& rhs ) const + { + bool sameIndex = (rhs.m_Index < m_Index); + + return sameIndex; + } + + + + //typename boost::iterator_facade< constant_iterator< value_type >, value_type, + //constant_iterator_tag, value_type, int >::reference dereference( ) const + //{ + // //value_type tmp = *(m_devMemory->data()); + // //return tmp; + // + // //return *(m_devMemory->data()); + // + // return m_constValue; + // + //} + + int operator*() const restrict(cpu,amp) + { + int xy = m_constValue; + return xy; + //return *(m_Ptr->data()); + } + + + int operator[](int x) const restrict(cpu,amp) + { + int xy = m_constValue; + return xy; + //return *(m_Ptr->data()); + } + + + //concurrency::array* m_devMemory; + //concurrency::array_view* m_Ptr; + value_type m_constValue; + }; + //) + + + template< typename Type > + constant_iterator< Type > make_constant_iterator( Type constValue ) + { + constant_iterator< Type > tmp( constValue ); + return tmp; + } + +} +} + + +#endif diff --git a/include/bolt/amp/iterator/counting_iterator.h b/include/bolt/amp/iterator/counting_iterator.h new file mode 100644 index 00000000..cae4592b --- /dev/null +++ b/include/bolt/amp/iterator/counting_iterator.h @@ -0,0 +1,182 @@ +/*************************************************************************** +* Copyright 2012 - 2013 Advanced Micro Devices, Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + +***************************************************************************/ +#pragma once +#if !defined( BOLT_CL_COUNTING_ITERATOR_H ) +#define BOLT_CL_COUNTING_ITERATOR_H +#include "bolt/amp/bolt.h" +#include "bolt/amp/iterator/iterator_traits.h" +#include + +/*! \file bolt/cl/iterator/counting_iterator.h + \brief Return Same Value or counting Value on dereferencing. +*/ + + +namespace bolt { +namespace amp { + + struct counting_iterator_tag + : public fancy_iterator_tag + { // identifying tag for random-access iterators + }; + + template< typename value_type > + class counting_iterator: public std::iterator< counting_iterator_tag, typename value_type, int> + { + public: + typedef typename boost::iterator_facade< counting_iterator< value_type >, value_type, + counting_iterator_tag, value_type, int >::difference_type difference_type; + + typedef concurrency::array_view< value_type > arrayview_type; + typedef counting_iterator const_iterator; + + + // Basic constructor requires a reference to the container and a positional element + counting_iterator( value_type init, const control& ctl = control::getDefault( ) ): + m_initValue( init ), m_Index( 0 ) {} + + // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa + template< typename OtherType > + counting_iterator( const counting_iterator< OtherType >& rhs ):m_Index( rhs.m_Index ), + m_initstValue( rhs.m_initstValue ) {} + + // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa + counting_iterator< value_type >& operator= ( const counting_iterator< value_type >& rhs ) + { + if( this == &rhs ) + return *this; + + m_initstValue = rhs.m_initstValue; + m_Index = rhs.m_Index; + return *this; + } + + counting_iterator< value_type >& operator+= ( const difference_type & n ) + { + advance( n ); + return *this; + } + + const counting_iterator< value_type > operator+ ( const difference_type & n ) const + { + counting_iterator< value_type > result( *this ); + result.advance( n ); + return result; + } + + const counting_iterator< value_type > & getBuffer( const_iterator itr ) const + { + return *this; + } + + + const counting_iterator< value_type > & getContainer( ) const + { + return *this; + } + + difference_type operator- ( const counting_iterator< value_type >& rhs ) const + { + return m_Index - rhs.m_Index; + } + + // Public member variables + difference_type m_Index; + + //private: + + // Used for templatized copy constructor and the templatized equal operator + template < typename > friend class counting_iterator; + + // For a counting_iterator, do nothing on an advance + void advance( difference_type n ) + { + m_Index += n; + } + + void operator++( ) + { + advance( 1 ); + } + + void operator--( ) + { + advance( -1 ); + } + + difference_type getIndex() const + { + return m_Index; + } + + template< typename OtherType > + bool operator== ( const counting_iterator< OtherType >& rhs ) const + { + bool sameIndex = (rhs.m_initValue == m_initValue) && (rhs.m_Index == m_Index); + + return sameIndex; + } + + template< typename OtherType > + bool operator!= ( const counting_iterator< OtherType >& rhs ) const + { + bool sameIndex = (rhs.m_initValue != m_initValue) || (rhs.m_Index != m_Index); + + return sameIndex; + } + + // Do we need this? Debug error + template< typename OtherType > + bool operator< ( const counting_iterator< OtherType >& rhs ) const + { + bool sameIndex = (rhs.m_Index < m_Index); + + return sameIndex; + } + + // Dereference operators + int operator*() const restrict(cpu,amp) + { + int xy = m_initValue; + return xy; + } + + + int operator[](int x) const restrict(cpu,amp) + { + int temp = x + m_initValue; + return temp; + } + + + value_type m_initValue; + }; + //) + + + template< typename Type > + counting_iterator< Type > make_counting_iterator( Type constValue ) + { + counting_iterator< Type > tmp( constValue ); + return tmp; + } + +} +} + + +#endif diff --git a/include/bolt/amp/iterator/iterator_facade.h b/include/bolt/amp/iterator/iterator_facade.h new file mode 100644 index 00000000..3643c2cd --- /dev/null +++ b/include/bolt/amp/iterator/iterator_facade.h @@ -0,0 +1,129 @@ +/*************************************************************************** +* Copyright 2012 - 2013 Advanced Micro Devices, Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + +***************************************************************************/ + +#pragma once +#if !defined( BOLT_AMP_ITERATOR_FACADE_H ) +#define BOLT_AMP_ITERATOR_FACADE_H + +/*! \file bolt/amp/iterator/iterator_facade.h + \brief +*/ + +namespace bolt { + + template < + class Derived // The derived iterator type being constructed + , class Value + , class CategoryOrTraversal + , class Reference = Value& + , class Difference = std::ptrdiff_t + > + class iterator_facade + { + private: + // + // Curiously Recurring Template interface. + // + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } + + protected: + // For use by derived classes + typedef iterator_facade iterator_facade_; + + public: + + typedef typename associated_types::value_type value_type; + typedef Reference reference; + typedef Difference difference_type; + + typedef typename operator_arrow_dispatch_::result_type pointer; + + typedef typename associated_types::iterator_category iterator_category; + + reference operator*() const + { + return iterator_core_access::dereference(this->derived()); + } + + pointer operator->() const + { + return operator_arrow_dispatch_::apply(*this->derived()); + } + + typename boost::detail::operator_brackets_result::type + operator[](difference_type n) const + { + typedef boost::detail::use_operator_brackets_proxy use_proxy; + + return boost::detail::make_operator_brackets_result( + this->derived() + n + , use_proxy() + ); + } + + Derived& operator++() + { + iterator_core_access::increment(this->derived()); + return this->derived(); + } + + Derived& operator--() + { + iterator_core_access::decrement(this->derived()); + return this->derived(); + } + + Derived operator--(int) + { + Derived tmp(this->derived()); + --*this; + return tmp; + } + + Derived& operator+=(difference_type n) + { + iterator_core_access::advance(this->derived(), n); + return this->derived(); + } + + Derived& operator-=(difference_type n) + { + iterator_core_access::advance(this->derived(), -n); + return this->derived(); + } + + Derived operator-(difference_type x) const + { + Derived result(this->derived()); + return result -= x; + } + + }; + + + +}; + +#endif \ No newline at end of file diff --git a/include/bolt/amp/iterator/iterator_traits.h b/include/bolt/amp/iterator/iterator_traits.h index be05ffcb..17e66266 100644 --- a/include/bolt/amp/iterator/iterator_traits.h +++ b/include/bolt/amp/iterator/iterator_traits.h @@ -59,6 +59,10 @@ namespace amp { typedef const T& reference; }; + struct fancy_iterator_tag : public std::random_access_iterator_tag + { + }; + } }; diff --git a/test/amp/TransformTest/TransformTest.cpp b/test/amp/TransformTest/TransformTest.cpp index 25d68f89..cb7d0eed 100644 --- a/test/amp/TransformTest/TransformTest.cpp +++ b/test/amp/TransformTest/TransformTest.cpp @@ -22,165 +22,16 @@ #include #include #include "bolt/amp/functional.h" +#include "bolt/amp/iterator/constant_iterator.h" +#include "bolt/amp/iterator/counting_iterator.h" #include "common/test_common.h" #define TEST_DOUBLE 0 #define GTEST_TESTS 1 -#if !GTEST_TESTS - - template - static void printA2(const char * msg, const Container &a, const Container &b, int x_size) - { - std::wcout << msg << std::endl; - for (int i = 0; i < x_size; i++) - std::wcout << a[i] << "\t" << b[i] << std::endl; - }; - - static void printA(const char * msg, const int *a, int x_size) - { - std::wcout << msg << std::endl; - for (int i = 0; i < x_size; i++) - std::wcout << a[i] << std::endl; - }; - - - - /* - * Demonstrates: - * Use of bolt::transform function - * Bolt delivers same result as stl::transform - * Bolt syntax is similar to STL transform - * Works for both integer arrays and STL vectors - */ - void simpleTransform1() - { - const int aSize = 16; - int a[aSize] = {4,0,5,5,0,5,5,1,3,1,0,3,1,1,3,5}; - int b[aSize] = {1,9,0,8,6,1,7,7,1,0,1,3,5,7,9,8}; - int out[aSize]; - std::transform(a,a+aSize, out, std::negate()); - bolt::amp::transform(a, a+aSize, out, bolt::negate()); - printA2("Transform Neg - From Pointer", a, out, aSize); - - bolt::amp::transform(a, a+aSize, b, out, bolt::plus()); - printA("\nTransformVaddOut", out, aSize); - - static const int vSz=16; - std::vector vec(16); - std::generate(vec.begin(), vec.end(), rand); - std::vector outVec(16); - //std::transform(vec.begin(),vec.end(), outVec.begin(), std::negate()); - bolt::amp::transform(vec.begin(),vec.end(), outVec.begin(), bolt::negate()); - std::cout<<"Printing"; - for(unsigned int i=0; i < 16; i++) - std::cout< - void simpleTransform2(const int sz) - { - std::vector A(sz); - std::vector S(sz); - std::vector B(sz); - - for (int i=0; i < sz; i++) { - //A[i] = T(i); // sequential assignment - A[i] = T(rand())/137; // something a little more exciting. - }; - - std::transform (A.begin(), A.end(), S.begin(), std::negate()); // single-core CPU version - bolt::amp::transform(A.begin(), A.end(), B.begin(), bolt::negate()); // bolt version on GPU or mcore CPU. - - // Check result: - const int maxErrCount = 10; - int errCount = 0; - for (unsigned x=0; x< S.size(); x++) { - const T s = S[x]; - const T b = B[x]; - //std::cout << s << "," << b << std::endl; - if ((s != b) && (++errCount < maxErrCount)) { - std::cout << "ERROR#" << errCount << " " << s << "!=" << b << std::endl; - }; - }; - }; - - - //// Show use of Saxpy Functor object. - //struct SaxpyFunctor - //{ - // float _a; - // SaxpyFunctor(float a) : _a(a) {}; - - // float operator() (const float &xx, const float &yy) restrict(cpu,amp) - // { - // return _a * xx + yy; - // }; - - //}; - - - //void transformSaxpy(int aSize) - //{ - // std::string fName = __FUNCTION__ ; - // fName += ":"; - - // std::vector A(aSize), B(aSize), Z1(aSize), Z0(aSize); - - // for (int i=0; i(128); - simpleTransform2(1000); - simpleTransform2(100000); - - // transformSaxpy(256); - }; - - - int _tmain(int argc, _TCHAR* argv[]) - { - simpleTransform(); - return 0; - } - - -#else - -///////////////////////////////////////////////////////////////////////////////////////////////////////// -// Fixture classes are now defined to enable googletest to process type parameterized tests - -// This class creates a C++ 'TYPE' out of a size_t value +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +//// Fixture classes are now defined to enable googletest to process type parameterized tests +// +//// This class creates a C++ 'TYPE' out of a size_t value template< size_t N > class TypeValue { @@ -291,7 +142,7 @@ class TransformOutPlaceArrayTest: public ::testing::Test int m_Errors; }; -// Explicit initialization of the C++ static const +//// Explicit initialization of the C++ static const template< typename ArrayTuple > const size_t TransformArrayTest< ArrayTuple >::ArraySize; @@ -1643,6 +1494,7 @@ TEST( TransformStdVector, SerialOutOfPlaceTransform) cmpArrays(hVectorO, SVectorO); } + TEST( TransformStdVector, MulticoreOutOfPlaceTransform) { int length = 1<<8; @@ -1777,16 +1629,65 @@ typedef ::testing::Types< //> UDDTests; +TEST(TransformStdVector, ConstantIterator) +{ + int length = 1 << 8; + std::vector hVectorA(length), hVectorO(length), hVectorB(length); + bolt::amp::constant_iterator hB(100); + bolt::amp::constant_iterator hB2 = hB + length; + + std::fill(hVectorA.begin(), hVectorA.end(), 1024); + std::fill(hVectorB.begin(), hVectorB.end(), 100); + + std::vector SVectorA(hVectorA.begin(), hVectorA.end()), + SVectorO(hVectorO.begin(), hVectorO.end()); + + //bolt::amp::device_vector hB(hVectorA.begin(), hVectorA.end()); + + std::transform(hVectorB.begin(), hVectorB.end(), hVectorA.begin(), hVectorO.begin(), std::plus< int >()); +// std::transform(hB.begin(), hB.end(), hVectorA.begin(), hVectorO.begin(), std::plus()); + bolt::amp::transform(hB, + hB2, + SVectorA.begin(), + SVectorO.begin(), + bolt::amp::plus< int >()); + + cmpArrays(hVectorO, SVectorO); +} + + + +TEST(TransformStdVector, CountingIterator) +{ + int length = 1 << 8; + std::vector hVectorA(length), hVectorO(length), hVectorB(length); + bolt::amp::counting_iterator hB(100); + bolt::amp::counting_iterator hB2 = hB + length; + + std::fill(hVectorA.begin(), hVectorA.end(), 1024); + + for( int i = 0; i < length ; i++ ) + { + hVectorB[i] = 100 + i; + } + + std::vector SVectorA(hVectorA.begin(), hVectorA.end()), + SVectorO(hVectorO.begin(), hVectorO.end()); + + + std::transform(hVectorB.begin(), hVectorB.end(), hVectorA.begin(), hVectorO.begin(), std::plus< int >()); + + bolt::amp::transform(hB, + hB2, + SVectorA.begin(), + SVectorO.begin(), + bolt::amp::plus< int >()); + + cmpArrays(hVectorO, SVectorO); +} -INSTANTIATE_TYPED_TEST_CASE_P( Integer, TransformArrayTest, IntegerTests ); -INSTANTIATE_TYPED_TEST_CASE_P( Float, TransformArrayTest, FloatTests ); -INSTANTIATE_TYPED_TEST_CASE_P( Integer, TransformBinaryArrayTest, IntegerTests ); -INSTANTIATE_TYPED_TEST_CASE_P( Float, TransformBinaryArrayTest, FloatTests ); -INSTANTIATE_TYPED_TEST_CASE_P( Integer, TransformOutPlaceArrayTest, IntegerTests ); -INSTANTIATE_TYPED_TEST_CASE_P( Float, TransformOutPlaceArrayTest, FloatTests ); -//INSTANTIATE_TYPED_TEST_CASE_P( UDDTest, TransformArrayTest, UDDTests ); int main(int argc, char* argv[]) { @@ -1839,5 +1740,4 @@ int main(int argc, char* argv[]) return retVal; -} -#endif \ No newline at end of file +} \ No newline at end of file