Newer
Older
/***************************************************************************
ArrayOperationsMIC_impl.h - description
-------------------
begin : Mar 4, 2017
copyright : (C) 2017 by Tomas Oberhuber
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/* See Copyright Notice in tnl/Copyright */
#include <iostream>
#include <TNL/tnlConfig.h>
#include <TNL/Math.h>
#include <TNL/Exceptions/MICSupportMissing.h>
#include <TNL/Exceptions/MICBadAlloc.h>
#include <TNL/Containers/Algorithms/ArrayOperations.h>
#include <TNL/Containers/Algorithms/Reduction.h>
#include <TNL/Containers/Algorithms/reduction-operations.h>
namespace TNL {
namespace Containers {
static constexpr std::size_t MIC_STACK_VAR_LIM = 5*1024*1024;
template< typename Element, typename Index >
ArrayOperations< Devices::MIC >::
allocateMemory( Element*& data,
const Index size )
{
#ifdef HAVE_MIC
data = (Element*) Devices::MIC::AllocMIC( size * sizeof(Element) );
if( ! data )
throw Exceptions::MICBadAlloc();
throw Exceptions::MICSupportMissing();
#endif
}
template< typename Element >
ArrayOperations< Devices::MIC >::
freeMemory( Element* data )
{
TNL_ASSERT( data, );
#ifdef HAVE_MIC
throw Exceptions::MICSupportMissing();
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#endif
}
template< typename Element >
void
ArrayOperations< Devices::MIC >::
setMemoryElement( Element* data,
const Element& value )
{
TNL_ASSERT( data, );
ArrayOperations< Devices::MIC >::setMemory( data, value, 1 );
}
template< typename Element >
Element
ArrayOperations< Devices::MIC >::
getMemoryElement( const Element* data )
{
TNL_ASSERT( data, );
Element result;
ArrayOperations< Devices::Host, Devices::MIC >::copyMemory< Element, Element, int >( &result, data, 1 );
return result;
}
template< typename Element, typename Index >
Element&
ArrayOperations< Devices::MIC >::
getArrayElementReference( Element* data, const Index i )
{
TNL_ASSERT( data, );
return data[ i ];
}
template< typename Element, typename Index >
const
Element& ArrayOperations< Devices::MIC >::
getArrayElementReference( const Element* data, const Index i )
{
TNL_ASSERT( data, );
return data[ i ];
}
template< typename Element, typename Index >
bool
ArrayOperations< Devices::MIC >::
setMemory( Element* data,
const Element& value,
const Index size )
{
TNL_ASSERT( data, );
#ifdef HAVE_MIC
Element tmp=value;
Devices::MICHider<Element> hide_ptr;
hide_ptr.pointer=data;
#pragma offload target(mic) in(hide_ptr,tmp,size)
{
Element * dst= hide_ptr.pointer;
for(int i=0;i<size;i++)
dst[i]=tmp;
}
return true;
#else
throw Exceptions::MICSupportMissing();
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#endif
}
template< typename DestinationElement,
typename SourceElement,
typename Index >
bool
ArrayOperations< Devices::MIC >::
copyMemory( DestinationElement* destination,
const SourceElement* source,
const Index size )
{
TNL_ASSERT( destination, );
TNL_ASSERT( source, );
#ifdef HAVE_MIC
if( std::is_same< DestinationElement, SourceElement >::value )
{
Devices::MICHider<void> src_ptr;
src_ptr.pointer=(void*)source;
Devices::MICHider<void> dst_ptr;
dst_ptr.pointer=(void*)destination;
#pragma offload target(mic) in(src_ptr,dst_ptr,size)
{
memcpy(dst_ptr.pointer,src_ptr.pointer,size*sizeof(DestinationElement));
}
return true;
}
else
{
Devices::MICHider<const SourceElement> src_ptr;
src_ptr.pointer=source;
Devices::MICHider<DestinationElement> dst_ptr;
dst_ptr.pointer=destination;
#pragma offload target(mic) in(src_ptr,dst_ptr,size)
{
for(int i=0;i<size;i++)
dst_ptr.pointer[i]=src_ptr.pointer[i];
}
return true;
throw Exceptions::MICSupportMissing();
#endif
return false;
}
template< typename Element1,
typename Element2,
typename Index >
bool
ArrayOperations< Devices::MIC >::
compareMemory( const Element1* destination,
const Element2* source,
const Index size )
{
TNL_ASSERT( destination, );
TNL_ASSERT( source, );
#ifdef HAVE_MIC
if( std::is_same< Element1, Element2 >::value )
{
Devices::MICHider<void> src_ptr;
src_ptr.pointer=(void*)source;
Devices::MICHider<void> dst_ptr;
dst_ptr.pointer=(void*)destination;
int ret=0;
#pragma offload target(mic) in(src_ptr,dst_ptr,size) out(ret)
ret=memcmp(dst_ptr.pointer,src_ptr.pointer,size*sizeof(Element1));
if(ret==0)
return true;
}
else
{
Devices::MICHider<const Element1> src_ptr;
src_ptr.pointer=source;
Devices::MICHider<const Element2> dst_ptr;
dst_ptr.pointer=destination;
bool ret=false;
#pragma offload target(mic) in(src_ptr,dst_ptr,size) out(ret)
int i=0;
for(i=0;i<size;i++)
if(dst_ptr.pointer[i]!=src_ptr.pointer[i])
break;
if(i==size)
ret=true;
else
ret=false;
return ret;
}
return false;
#else
throw Exceptions::MICSupportMissing();
#endif
}
/****
* Operations MIC -> Host
*/
template< typename DestinationElement,
typename SourceElement,
typename Index >
bool
ArrayOperations< Devices::Host, Devices::MIC >::
copyMemory( DestinationElement* destination,
const SourceElement* source,
const Index size )
{
TNL_ASSERT( destination, );
TNL_ASSERT( source, );
#ifdef HAVE_MIC
if( std::is_same< DestinationElement, SourceElement >::value )
{
Devices::MICHider<void> src_ptr;
src_ptr.pointer=(void*)source;
//JAKA KONSTANTA se vejde do stacku 5MB?
if(size<MIC_STACK_VAR_LIM)
uint8_t tmp[size*sizeof(SourceElement)];
#pragma offload target(mic) in(src_ptr,size) out(tmp)
memcpy((void*)&tmp,src_ptr.pointer,size*sizeof(SourceElement));
memcpy((void*)destination,(void*)&tmp,size*sizeof(SourceElement));
return true;
//direct -- pomalejší
uint8_t* tmp=(uint8_t*)destination;
#pragma offload target(mic) in(src_ptr,size) out(tmp:length(size))
{
memcpy((void*)tmp,src_ptr.pointer,size*sizeof(SourceElement));
}
return true;
}
}
else
{
Devices::MICHider<const SourceElement> src_ptr;
src_ptr.pointer=source;
if(size<MIC_STACK_VAR_LIM)
{
uint8_t tmp[size*sizeof(DestinationElement)];
#pragma offload target(mic) in(src_ptr,size) out(tmp)
DestinationElement *dst=(DestinationElement*)&tmp;
for(int i=0;i<size;i++)
dst[i]=src_ptr.pointer[i];
memcpy((void*)destination,(void*)&tmp,size*sizeof(DestinationElement));
return true;
else
{
//direct pseudo heap-- pomalejší
uint8_t* tmp=(uint8_t*)destination;
#pragma offload target(mic) in(src_ptr,size) out(tmp:length(size*sizeof(DestinationElement)))
{
DestinationElement *dst=(DestinationElement*)tmp;
for(int i=0;i<size;i++)
dst[i]=src_ptr.pointer[i];
}
return true;
}
}
#else
throw Exceptions::MICSupportMissing();
#endif
}
template< typename Element1,
typename Element2,
typename Index >
bool
ArrayOperations< Devices::Host, Devices::MIC >::
compareMemory( const Element1* destination,
const Element2* source,
const Index size )
{
/***
* Here, destination is on host and source is on MIC device.
*/
TNL_ASSERT( destination, );
TNL_ASSERT( source, );
TNL_ASSERT( size >= 0, std::cerr << "size = " << size );
#ifdef HAVE_MIC
Index compared( 0 );
Index transfer( 0 );
std::size_t max_transfer=MIC_STACK_VAR_LIM/sizeof(Element2);
uint8_t host_buffer[max_transfer*sizeof(Element2)];
Devices::MICHider<const Element2> src_ptr;
while( compared < size )
{
transfer=min(size-compared,max_transfer);
src_ptr.pointer=source+compared;
#pragma offload target(mic) out(host_buffer) in(src_ptr,transfer)
{
memcpy((void*)&host_buffer,(void*)src_ptr.pointer,transfer*sizeof(Element2));
}
if( ! ArrayOperations< Devices::Host >::compareMemory( &destination[ compared ], (Element2*)&host_buffer, transfer ) )
{
return false;
}
compared += transfer;
}
return true;
#else
throw Exceptions::MICSupportMissing();
#endif
}
/****
* Operations Host -> MIC
*/
template< typename DestinationElement,
typename SourceElement,
typename Index >
bool
ArrayOperations< Devices::MIC, Devices::Host >::
copyMemory( DestinationElement* destination,
const SourceElement* source,
const Index size )
{
TNL_ASSERT( destination, );
TNL_ASSERT( source, );
TNL_ASSERT( size >= 0, std::cerr << "size = " << size );
#ifdef HAVE_MIC
if( std::is_same< DestinationElement, SourceElement >::value )
{
Devices::MICHider<void> dst_ptr;
dst_ptr.pointer=(void*)destination;
//JAKA KONSTANTA se vejde do stacku 5MB?
if(size<MIC_STACK_VAR_LIM)
uint8_t tmp[size*sizeof(SourceElement)];
memcpy((void*)&tmp,(void*)source,size*sizeof(SourceElement));
#pragma offload target(mic) in(dst_ptr,tmp,size)
memcpy(dst_ptr.pointer,(void*)&tmp,size*sizeof(SourceElement));
//direct pseudo heap-- pomalejší
uint8_t* tmp=(uint8_t*)source;
#pragma offload target(mic) in(dst_ptr,size) in(tmp:length(size))
{
memcpy(dst_ptr.pointer,(void*)tmp,size*sizeof(SourceElement));
}
return true;
}
}
else
{
Devices::MICHider<DestinationElement> dst_ptr;
dst_ptr.pointer=destination;
if(size<MIC_STACK_VAR_LIM)
{
uint8_t tmp[size*sizeof(SourceElement)];
memcpy((void*)&tmp,(void*)source,size*sizeof(SourceElement));
#pragma offload target(mic) in(dst_ptr,size,tmp)
SourceElement *src=(SourceElement*)&tmp;
for(int i=0;i<size;i++)
dst_ptr.pointer[i]=src[i];
else
{
//direct pseudo heap-- pomalejší
uint8_t* tmp=(uint8_t*)source;
#pragma offload target(mic) in(dst_ptr,size) in(tmp:length(size*sizeof(SourceElement)))
{
SourceElement *src=(SourceElement*)tmp;
for(int i=0;i<size;i++)
dst_ptr.pointer[i]=src[i];
}
return true;
}
}
#else
throw Exceptions::MICSupportMissing();
#endif
}
template< typename Element1,
typename Element2,
typename Index >
bool
ArrayOperations< Devices::MIC, Devices::Host >::
compareMemory( const Element1* hostData,
const Element2* deviceData,
const Index size )
{
TNL_ASSERT( hostData, );
TNL_ASSERT( deviceData, );
TNL_ASSERT( size >= 0, std::cerr << "size = " << size );
return ArrayOperations< Devices::Host, Devices::MIC >::compareMemory( deviceData, hostData, size );
}
} // namespace Algorithms
} // namespace Containers
} // namespace TNL