| 96 | |
| 97 | template<typename T> |
| 98 | void memcopy(Param<T> out, CParam<T> in, dim_t indims) { |
| 99 | const size_t totalSize{in.elements() * sizeof(T) * 2}; |
| 100 | removeEmptyColumns(in.dims, indims, out.strides); |
| 101 | indims = removeEmptyColumns(in.dims, indims, in.dims, in.strides); |
| 102 | indims = combineColumns(in.dims, in.strides, indims, out.strides); |
| 103 | |
| 104 | // Optimization memory access and caching. |
| 105 | // Best performance is achieved with the highest vectorization |
| 106 | // (<int> --> <int2>,<int4>, ...), since more data is processed per IO. |
| 107 | |
| 108 | // 16 Bytes gives best performance (=cdouble) |
| 109 | const dim_t maxVectorWidth{sizeof(T) > 8 ? 1 : 16 / sizeof(T)}; |
| 110 | const dim_t vectorWidth{vectorizeShape(maxVectorWidth, out, indims, in)}; |
| 111 | const size_t sizeofNewT{sizeof(T) * vectorWidth}; |
| 112 | |
| 113 | threadsMgt<dim_t> th(in.dims, indims); |
| 114 | const dim3 threads{th.genThreads()}; |
| 115 | const dim3 blocks{th.genBlocks(threads, 1, 1, totalSize, sizeofNewT)}; |
| 116 | |
| 117 | EnqueueArgs qArgs(blocks, threads, getActiveStream()); |
| 118 | |
| 119 | // select the kernel with the necessary loopings |
| 120 | const char *kernelName{th.loop0 ? "arrayfire::cuda::memCopyLoop0" |
| 121 | : th.loop2 ? "arrayfire::cuda::memCopyLoop123" |
| 122 | : th.loop1 ? th.loop3 |
| 123 | ? "arrayfire::cuda::memCopyLoop13" |
| 124 | : "arrayfire::cuda::memCopyLoop1" |
| 125 | : th.loop3 ? "arrayfire::cuda::memCopyLoop3" |
| 126 | : "arrayfire::cuda::memCopy"}; |
| 127 | |
| 128 | // Conversion to cuda base vector types. |
| 129 | switch (sizeofNewT) { |
| 130 | case 1: { |
| 131 | auto memCopy{common::getKernel(kernelName, {{memcopy_cuh_src}}, |
| 132 | TemplateArgs(TemplateArg("char")))}; |
| 133 | memCopy(qArgs, Param<char>((char *)out.ptr, out.dims, out.strides), |
| 134 | CParam<char>((const char *)in.ptr, in.dims, in.strides)); |
| 135 | } break; |
| 136 | case 2: { |
| 137 | auto memCopy{common::getKernel(kernelName, {{memcopy_cuh_src}}, |
| 138 | TemplateArgs(TemplateArg("short")))}; |
| 139 | memCopy(qArgs, |
| 140 | Param<short>((short *)out.ptr, out.dims, out.strides), |
| 141 | CParam<short>((const short *)in.ptr, in.dims, in.strides)); |
| 142 | } break; |
| 143 | case 4: { |
| 144 | auto memCopy{common::getKernel(kernelName, {{memcopy_cuh_src}}, |
| 145 | TemplateArgs(TemplateArg("float")))}; |
| 146 | memCopy(qArgs, |
| 147 | Param<float>((float *)out.ptr, out.dims, out.strides), |
| 148 | CParam<float>((const float *)in.ptr, in.dims, in.strides)); |
| 149 | } break; |
| 150 | case 8: { |
| 151 | auto memCopy{ |
| 152 | common::getKernel(kernelName, {{memcopy_cuh_src}}, |
| 153 | TemplateArgs(TemplateArg("float2")))}; |
| 154 | memCopy( |
| 155 | qArgs, Param<float2>((float2 *)out.ptr, out.dims, out.strides), |
nothing calls this directly
no test coverage detected