| 96 | |
| 97 | template<typename T> |
| 98 | void memcopy(const cl::Buffer& b_out, const dim4& ostrides, |
| 99 | const cl::Buffer& b_in, const dim4& idims, const dim4& istrides, |
| 100 | dim_t ioffset, const dim_t indims, dim_t ooffset = 0) { |
| 101 | dims_type idims_{ |
| 102 | static_cast<int>(idims.dims[0]), static_cast<int>(idims.dims[1]), |
| 103 | static_cast<int>(idims.dims[2]), static_cast<int>(idims.dims[3])}; |
| 104 | dims_type istrides_{ |
| 105 | static_cast<int>(istrides.dims[0]), static_cast<int>(istrides.dims[1]), |
| 106 | static_cast<int>(istrides.dims[2]), static_cast<int>(istrides.dims[3])}; |
| 107 | dims_type ostrides_{ |
| 108 | static_cast<int>(ostrides.dims[0]), static_cast<int>(ostrides.dims[1]), |
| 109 | static_cast<int>(ostrides.dims[2]), static_cast<int>(ostrides.dims[3])}; |
| 110 | int indims_{static_cast<int>(indims)}; |
| 111 | |
| 112 | const size_t totalSize{idims.elements() * sizeof(T) * 2}; |
| 113 | removeEmptyColumns(idims_.dims, indims_, ostrides_.dims); |
| 114 | indims_ = |
| 115 | removeEmptyColumns(idims_.dims, indims_, idims_.dims, istrides_.dims); |
| 116 | indims_ = |
| 117 | combineColumns(idims_.dims, istrides_.dims, indims_, ostrides_.dims); |
| 118 | |
| 119 | // Optimization memory access and caching. |
| 120 | // Best performance is achieved with the highest vectorization |
| 121 | // (<int> --> <int2>,<int4>, ...), since more data is processed per IO. |
| 122 | const cl::Device dev{opencl::getDevice()}; |
| 123 | const unsigned DevicePreferredVectorWidthChar{ |
| 124 | dev.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR>()}; |
| 125 | // When the architecture prefers some width's, it is certainly |
| 126 | // on char. No preference means vector width 1 returned. |
| 127 | const bool DevicePreferredVectorWidth{DevicePreferredVectorWidthChar != 1}; |
| 128 | size_t maxVectorWidth{ |
| 129 | DevicePreferredVectorWidth |
| 130 | ? sizeof(T) == 1 ? DevicePreferredVectorWidthChar |
| 131 | : sizeof(T) == 2 |
| 132 | ? dev.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT>() |
| 133 | : sizeof(T) == 4 |
| 134 | ? dev.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT>() |
| 135 | : sizeof(T) == 8 |
| 136 | ? dev.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE>() |
| 137 | : 1 |
| 138 | : sizeof(T) > 8 ? 1 |
| 139 | : 16 / sizeof(T)}; |
| 140 | const size_t vectorWidth{vectorizeShape(maxVectorWidth, idims_.dims, |
| 141 | istrides_.dims, indims_, ioffset, |
| 142 | ostrides_.dims, ooffset)}; |
| 143 | const size_t sizeofNewT{sizeof(T) * vectorWidth}; |
| 144 | |
| 145 | threadsMgt<int> th(idims_.dims, indims_, 1, 1, totalSize, sizeofNewT); |
| 146 | const char* kernelName{ |
| 147 | th.loop0 ? "memCopyLoop0" |
| 148 | : th.loop1 ? th.loop3 ? "memCopyLoop13" : "memCopyLoop1" |
| 149 | : th.loop3 ? "memCopyLoop3" |
| 150 | : "memCopy"}; // Conversion to base vector types. |
| 151 | TemplateArg tArg{ |
| 152 | sizeofNewT == 1 ? "char" |
| 153 | : sizeofNewT == 2 ? "short" |
| 154 | : sizeofNewT == 4 ? "float" |
| 155 | : sizeofNewT == 8 ? "float2" |
nothing calls this directly
no test coverage detected