| 55 | |
| 56 | template <typename T, bool conjugate> |
| 57 | void TransposeSimple(const GPUDevice& d, const Tensor& in, |
| 58 | const gtl::ArraySlice<int32> perm, Tensor* out) { |
| 59 | // Ensures we can use 32-bit index. |
| 60 | const int64 nelem = in.NumElements(); |
| 61 | CHECK_LT(nelem, kint32max) << "Tensor too large to transpose on GPU"; |
| 62 | // Pack strides and permutation into one buffer. |
| 63 | const int32 ndims = in.dims(); |
| 64 | gtl::InlinedVector<int32, 24> host_buf(ndims * 3); |
| 65 | gtl::InlinedVector<int32, 8> in_strides = ComputeStride<int32>(in.shape()); |
| 66 | gtl::InlinedVector<int32, 8> out_strides = ComputeStride<int32>(out->shape()); |
| 67 | // Dimension permutation. |
| 68 | for (int i = 0; i < ndims; ++i) { |
| 69 | host_buf[i] = in_strides[i]; |
| 70 | host_buf[ndims + i] = out_strides[i]; |
| 71 | host_buf[ndims * 2 + i] = perm[i]; |
| 72 | } |
| 73 | // Copies the input strides, output strides and permutation to the device. |
| 74 | auto num_bytes = sizeof(int64) * host_buf.size(); |
| 75 | auto dev_buf = d.allocate(num_bytes); |
| 76 | // NOTE: host_buf is not allocated by GpuHostAllocator, and |
| 77 | // therefore we are doing a sync copy effectively. |
| 78 | d.memcpyHostToDevice(dev_buf, host_buf.data(), num_bytes); |
| 79 | // Launch kernel to q[...] = p[...]. |
| 80 | const T* p = reinterpret_cast<const T*>(in.tensor_data().data()); |
| 81 | T* q = reinterpret_cast<T*>(const_cast<char*>((out->tensor_data().data()))); |
| 82 | GpuLaunchConfig cfg = GetGpuLaunchConfig(nelem, d); |
| 83 | TF_CHECK_OK(GpuLaunchKernel( |
| 84 | TransposeKernel<T, conjugate>, cfg.block_count, cfg.thread_per_block, 0, |
| 85 | d.stream(), cfg.virtual_thread_count, p, |
| 86 | reinterpret_cast<const int32*>(dev_buf), ndims, q)); |
| 87 | // Safe to deallocate immediately after the kernel launch. |
| 88 | d.deallocate(dev_buf); |
| 89 | } |
| 90 | |
| 91 | // TransposeUsingTile tries to reduce the dimension of the input tensor to 3 and |
| 92 | // then call special kernels to swap either dimension 1 and dimension 2 or |
nothing calls this directly
no test coverage detected