| 137 | } |
| 138 | |
| 139 | void ComputeAsync(OpKernelContext* context, DoneCallback done) final { |
| 140 | const Tensor& input = context->input(0); |
| 141 | const int ndims = input.dims(); |
| 142 | const int64 m = input.dim_size(ndims - 2); |
| 143 | const int64 n = input.dim_size(ndims - 1); |
| 144 | const int64 min_size = std::min(m, n); |
| 145 | const int64 batch_size = |
| 146 | input.template flat_inner_dims<Scalar, 3>().dimension(0); |
| 147 | |
| 148 | // Validate inputs. |
| 149 | OP_REQUIRES_ASYNC( |
| 150 | context, ndims >= 2, |
| 151 | errors::InvalidArgument("Input must have rank >= 2, got ", ndims), |
| 152 | done); |
| 153 | |
| 154 | // Allocate output. |
| 155 | // If full_matrices_ is true then Q is m x m and R is m x n. |
| 156 | // Otherwise, Q is m x min(m, n), and R is min(m, n) x n. |
| 157 | Tensor* q; |
| 158 | TensorShape q_shape = input.shape(); |
| 159 | q_shape.set_dim(ndims - 1, full_matrices_ ? m : min_size); |
| 160 | OP_REQUIRES_OK_ASYNC(context, context->allocate_output(0, q_shape, &q), |
| 161 | done); |
| 162 | Tensor* r; |
| 163 | TensorShape r_shape = input.shape(); |
| 164 | r_shape.set_dim(ndims - 2, full_matrices_ ? m : min_size); |
| 165 | OP_REQUIRES_OK_ASYNC(context, context->allocate_output(1, r_shape, &r), |
| 166 | done); |
| 167 | |
| 168 | if (input.NumElements() == 0) { |
| 169 | done(); |
| 170 | return; |
| 171 | } |
| 172 | |
| 173 | // TODO(rmlarsen): Convert to std::make_unique when available. |
| 174 | std::unique_ptr<CudaSolver> solver(new CudaSolver(context)); |
| 175 | |
| 176 | // Allocate temporaries. |
| 177 | Tensor input_transposed; |
| 178 | TensorShape transposed_shape = input.shape(); |
| 179 | transposed_shape.set_dim(ndims - 2, input.dim_size(ndims - 1)); |
| 180 | transposed_shape.set_dim(ndims - 1, input.dim_size(ndims - 2)); |
| 181 | |
| 182 | OP_REQUIRES_OK_ASYNC( |
| 183 | context, |
| 184 | solver->allocate_scoped_tensor(DataTypeToEnum<Scalar>::value, |
| 185 | transposed_shape, &input_transposed), |
| 186 | done); |
| 187 | |
| 188 | Tensor tau; |
| 189 | OP_REQUIRES_OK_ASYNC(context, |
| 190 | solver->allocate_scoped_tensor( |
| 191 | DataTypeToEnum<Scalar>::value, |
| 192 | TensorShape({batch_size, min_size}), &tau), |
| 193 | done); |
| 194 | |
| 195 | // Transpose input, since cuSolver uses column-major, while TensorFlow uses |
| 196 | // row-major storage. |
nothing calls this directly
no test coverage detected