| 96 | } |
| 97 | |
| 98 | SVDTestcase::Result SVDTestcase::run(SVDForward* opr) { |
| 99 | auto handle = opr->handle(); |
| 100 | auto src = make_tensor_h2d(handle, m_mat); |
| 101 | |
| 102 | // Deduce layout |
| 103 | TensorLayout u_layout, s_layout, vt_layout; |
| 104 | opr->param() = m_param; |
| 105 | opr->deduce_layout(m_mat.layout, u_layout, s_layout, vt_layout); |
| 106 | |
| 107 | // Alloc tensor on device |
| 108 | Tensor<> u{handle, u_layout}, s{handle, s_layout}, vt{handle, vt_layout}; |
| 109 | WorkspaceWrapper ws( |
| 110 | handle, |
| 111 | opr->get_workspace_in_bytes(m_mat.layout, u_layout, s_layout, vt_layout)); |
| 112 | |
| 113 | opr->exec(*src, u.tensornd(), s.tensornd(), vt.tensornd(), ws.workspace()); |
| 114 | |
| 115 | auto u_host = make_tensor_d2h(handle, u.tensornd()); |
| 116 | // Defined in wsdk8/Include/shared/inaddr.h Surprise! It's Windows. |
| 117 | #undef s_host |
| 118 | auto s_host = make_tensor_d2h(handle, s.tensornd()); |
| 119 | auto vt_host = make_tensor_d2h(handle, vt.tensornd()); |
| 120 | if (m_param.compute_uv) { |
| 121 | // Copy back singular value, build diag(s) |
| 122 | std::unique_ptr<dt_float32> diag_s_host_mem( |
| 123 | new dt_float32[m_mat.layout.span().dist_elem()]); |
| 124 | TensorLayout diag_layout = m_mat.layout; |
| 125 | if (!m_param.full_matrices) { |
| 126 | SmallVector<size_t> shape; |
| 127 | for (int i = 0; i < (int)diag_layout.ndim - 2; i++) { |
| 128 | shape.push_back(diag_layout[i]); |
| 129 | } |
| 130 | size_t x = std::min( |
| 131 | diag_layout[diag_layout.ndim - 1], |
| 132 | diag_layout[diag_layout.ndim - 2]); |
| 133 | shape.push_back(x); |
| 134 | shape.push_back(x); |
| 135 | diag_layout = {shape, diag_layout.dtype}; |
| 136 | } |
| 137 | TensorND diag_s_host{diag_s_host_mem.get(), diag_layout}; |
| 138 | fill_diag<dt_float32>(*s_host, diag_s_host); |
| 139 | |
| 140 | // Try to recover original matrix by u * diag(s) * vt |
| 141 | auto diag_s_dev = make_tensor_h2d(handle, diag_s_host); |
| 142 | auto tmp = matmul(handle, u.tensornd(), *diag_s_dev); |
| 143 | auto recovered = matmul(handle, tmp->tensornd(), vt.tensornd()); |
| 144 | return {u_host, s_host, vt_host, |
| 145 | make_tensor_d2h(handle, recovered->tensornd())}; |
| 146 | } |
| 147 | return {u_host, s_host, vt_host, nullptr}; |
| 148 | } |
| 149 | |
| 150 | // vim: syntax=cpp.doxygen |
no test coverage detected