-
Notifications
You must be signed in to change notification settings - Fork 769
SYCL: support 0-dim acc in handler::copy(accessor, accessor) #1551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
#pragma once | ||
|
||
#include <CL/sycl/access/access.hpp> | ||
#include <CL/sycl/atomic.hpp> | ||
#include <CL/sycl/context.hpp> | ||
#include <CL/sycl/detail/cg.hpp> | ||
#include <CL/sycl/detail/export.hpp> | ||
|
@@ -366,6 +367,107 @@ class __SYCL_EXPORT handler { | |
return true; | ||
} | ||
|
||
/// Handles some special cases of the copy operation from one accessor | ||
/// to another accessor. Returns true if the copy is handled here. | ||
/// | ||
/// \param Src is a source SYCL accessor. | ||
/// \param Dst is a destination SYCL accessor. | ||
// TODO: support atomic accessor in Src or/and Dst. | ||
template <typename TSrc, int DimSrc, access::mode ModeSrc, | ||
access::target TargetSrc, typename TDst, int DimDst, | ||
access::mode ModeDst, access::target TargetDst, | ||
access::placeholder IsPHSrc, access::placeholder IsPHDst> | ||
detail::enable_if_t<(DimSrc > 0) && (DimDst > 0), bool> | ||
copyAccToAccHelper(accessor<TSrc, DimSrc, ModeSrc, TargetSrc, IsPHSrc> Src, | ||
accessor<TDst, DimDst, ModeDst, TargetDst, IsPHDst> Dst) { | ||
if (!MIsHost && | ||
IsCopyingRectRegionAvailable(Src.get_range(), Dst.get_range())) | ||
return false; | ||
|
||
range<1> LinearizedRange(Src.get_count()); | ||
parallel_for<class __copyAcc2Acc<TSrc, DimSrc, ModeSrc, TargetSrc, | ||
TDst, DimDst, ModeDst, TargetDst, | ||
IsPHSrc, IsPHDst>> | ||
(LinearizedRange, [=](id<1> Id) { | ||
size_t Index = Id[0]; | ||
id<DimSrc> SrcIndex = getDelinearizedIndex(Src.get_range(), Index); | ||
id<DimDst> DstIndex = getDelinearizedIndex(Dst.get_range(), Index); | ||
Dst[DstIndex] = Src[SrcIndex]; | ||
}); | ||
return true; | ||
} | ||
|
||
template <typename T, int Dim, access::mode Mode, access::target Target, | ||
access::placeholder IsPH> | ||
detail::enable_if_t<Dim == 0 && Mode == access::mode::atomic, T> | ||
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) const { | ||
atomic<T, access::address_space::global_space> AtomicSrc = Src; | ||
return AtomicSrc.load(); | ||
} | ||
|
||
template <typename T, int Dim, access::mode Mode, access::target Target, | ||
access::placeholder IsPH> | ||
detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, T> | ||
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) const { | ||
id<Dim> Id = getDelinearizedIndex(Src.get_range(), 0); | ||
return Src[Id].load(); | ||
} | ||
|
||
template <typename T, int Dim, access::mode Mode, access::target Target, | ||
access::placeholder IsPH> | ||
detail::enable_if_t<Mode != access::mode::atomic, T> | ||
readFromFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Src) const { | ||
return *(Src.get_pointer()); | ||
} | ||
|
||
template <typename T, int Dim, access::mode Mode, access::target Target, | ||
access::placeholder IsPH> | ||
detail::enable_if_t<Dim == 0 && Mode == access::mode::atomic, void> | ||
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const { | ||
atomic<T, access::address_space::global_space> AtomicDst = Dst; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't it be a reference to atomic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The accessor operator[] and operator() return a value, not a reference. 93 /* Available only when: accessMode == access::mode::atomic && dimensions == Please clarify if I understood your comment incorrectly. |
||
AtomicDst.store(V); | ||
} | ||
|
||
template <typename T, int Dim, access::mode Mode, access::target Target, | ||
access::placeholder IsPH> | ||
detail::enable_if_t<(Dim > 0) && Mode == access::mode::atomic, void> | ||
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const { | ||
id<Dim> Id = getDelinearizedIndex(Dst.get_range(), 0); | ||
Dst[Id].store(V); | ||
} | ||
|
||
template <typename T, int Dim, access::mode Mode, access::target Target, | ||
access::placeholder IsPH> | ||
detail::enable_if_t<Mode != access::mode::atomic, void> | ||
writeToFirstAccElement(accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const { | ||
*(Dst.get_pointer()) = V; | ||
} | ||
|
||
/// Handles some special cases of the copy operation from one accessor | ||
/// to another accessor. Returns true if the copy is handled here. | ||
/// | ||
/// Source must have at least as many bytes as the range accessed by Dst. | ||
/// | ||
/// \param Src is a source SYCL accessor. | ||
/// \param Dst is a destination SYCL accessor. | ||
template <typename TSrc, int DimSrc, access::mode ModeSrc, | ||
access::target TargetSrc, typename TDst, int DimDst, | ||
access::mode ModeDst, access::target TargetDst, | ||
access::placeholder IsPHSrc, access::placeholder IsPHDst> | ||
detail::enable_if_t<DimSrc == 0 || DimDst == 0, bool> | ||
copyAccToAccHelper(accessor<TSrc, DimSrc, ModeSrc, TargetSrc, IsPHSrc> Src, | ||
accessor<TDst, DimDst, ModeDst, TargetDst, IsPHDst> Dst) { | ||
if (!MIsHost) | ||
return false; | ||
|
||
single_task<class __copyAcc2Acc<TSrc, DimSrc, ModeSrc, TargetSrc, | ||
TDst, DimDst, ModeDst, TargetDst, | ||
IsPHSrc, IsPHDst>> ([=]() { | ||
writeToFirstAccElement(Dst, readFromFirstAccElement(Src)); | ||
}); | ||
return true; | ||
} | ||
|
||
constexpr static bool isConstOrGlobal(access::target AccessTarget) { | ||
return AccessTarget == access::target::global_buffer || | ||
AccessTarget == access::target::constant_buffer; | ||
|
@@ -985,6 +1087,7 @@ class __SYCL_EXPORT handler { | |
/// | ||
/// \param Src is a source SYCL accessor. | ||
/// \param Dst is a pointer to destination memory. | ||
// TODO: support 0-dimensional and atomic accessors. | ||
template <typename T_Src, typename T_Dst, int Dims, access::mode AccessMode, | ||
access::target AccessTarget, | ||
access::placeholder IsPlaceholder = access::placeholder::false_t> | ||
|
@@ -1030,6 +1133,7 @@ class __SYCL_EXPORT handler { | |
/// | ||
/// \param Src is a pointer to source memory. | ||
/// \param Dst is a destination SYCL accessor. | ||
// TODO: support 0-dimensional and atomic accessors. | ||
template <typename T_Src, typename T_Dst, int Dims, access::mode AccessMode, | ||
access::target AccessTarget, | ||
access::placeholder IsPlaceholder = access::placeholder::false_t> | ||
|
@@ -1072,7 +1176,7 @@ class __SYCL_EXPORT handler { | |
/// Copies the contents of memory object accessed by Src to the memory | ||
/// object accessed by Dst. | ||
/// | ||
/// Source must have at least as many bytes as the range accessed by Dst. | ||
/// Dst must have at least as many bytes as the range accessed by Src. | ||
/// | ||
/// \param Src is a source SYCL accessor. | ||
/// \param Dst is a destination SYCL accessor. | ||
|
@@ -1093,32 +1197,10 @@ class __SYCL_EXPORT handler { | |
"Invalid source accessor target for the copy method."); | ||
static_assert(isValidTargetForExplicitOp(AccessTarget_Dst), | ||
"Invalid destination accessor target for the copy method."); | ||
// TODO replace to get_size() when it will provide correct values. | ||
assert( | ||
(Dst.get_range().size() * sizeof(T_Dst) >= | ||
Src.get_range().size() * sizeof(T_Src)) && | ||
"dest must have at least as many bytes as the range accessed by src."); | ||
if (MIsHost || | ||
!IsCopyingRectRegionAvailable(Src.get_range(), Dst.get_range())) { | ||
range<Dims_Src> CopyRange = Src.get_range(); | ||
size_t Range = 1; | ||
for (size_t I = 0; I < Dims_Src; ++I) | ||
Range *= CopyRange[I]; | ||
range<1> LinearizedRange(Range); | ||
parallel_for< class __copyAcc2Acc< T_Src, Dims_Src, AccessMode_Src, | ||
AccessTarget_Src, T_Dst, Dims_Dst, | ||
AccessMode_Dst, AccessTarget_Dst, | ||
IsPlaceholder_Src, | ||
IsPlaceholder_Dst>> | ||
(LinearizedRange, [=](id<1> Id) { | ||
size_t Index = Id[0]; | ||
id<Dims_Src> SrcIndex = getDelinearizedIndex(Src.get_range(), Index); | ||
id<Dims_Dst> DstIndex = getDelinearizedIndex(Dst.get_range(), Index); | ||
Dst[DstIndex] = Src[SrcIndex]; | ||
}); | ||
|
||
assert(Dst.get_size() >= Src.get_size() && | ||
"The destination accessor does not fit the copied memory."); | ||
if (copyAccToAccHelper(Src, Dst)) | ||
return; | ||
} | ||
MCGType = detail::CG::COPY_ACC_TO_ACC; | ||
|
||
detail::AccessorBaseHost *AccBaseSrc = (detail::AccessorBaseHost *)&Src; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we check here if
DimSrc == DimDst
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it is correct to copy from 1D accessor to 3D. It is probably correct. So, that check is not needed.
In my patch I do not change any constraints.
My patch only separates the existing code to this routine to make it possible to copy to/from 0-dim accessor.