|
12 | 12 | See the License for the specific language governing permissions and
|
13 | 13 | limitations under the License. */
|
14 | 14 |
|
| 15 | +#include <iostream> |
15 | 16 | #include <iterator>
|
| 17 | +#include <memory> |
16 | 18 | #include <string>
|
| 19 | +#include <vector> |
17 | 20 | #include "gtest/gtest.h"
|
| 21 | +#include "paddle/fluid/framework/details/inplace_op_pass.h" |
| 22 | +#include "paddle/fluid/framework/ir/pass_builder.h" |
18 | 23 | #include "paddle/fluid/framework/op_info.h"
|
19 | 24 | #include "paddle/fluid/framework/op_registry.h"
|
20 | 25 | #include "paddle/fluid/framework/operator.h"
|
@@ -165,118 +170,147 @@ REGISTER_OPERATOR(multi_out_grad, f::NOP, f::MultiOutGradInplaceInToOut,
|
165 | 170 | namespace paddle {
|
166 | 171 | namespace framework {
|
167 | 172 |
|
168 |
| -// TEST(InferInplace, SingleOpInplaceInToOut) { |
169 |
| -// ProgramDesc prog; |
170 |
| -// auto* op = prog.MutableBlock(0)->AppendOp(); |
171 |
| -// op->SetType("single_op"); |
172 |
| -// op->SetInput("X", {"test2_a", "test2_b", "test2_c"}); |
173 |
| -// op->SetOutput("Out", {"test2_out"}); |
174 |
| -// |
175 |
| -// prog.MutableBlock(0)->Var("test2_a")->SetType(proto::VarType::LOD_TENSOR); |
176 |
| -// prog.MutableBlock(0)->Var("test2_a")->SetShape({32, 64, 128, 128}); |
177 |
| -// prog.MutableBlock(0)->Var("test2_b")->SetType(proto::VarType::LOD_TENSOR); |
178 |
| -// prog.MutableBlock(0)->Var("test2_c")->SetType(proto::VarType::LOD_TENSOR); |
179 |
| -// prog.MutableBlock(0)->Var("test2_out"); |
180 |
| -// prog.MutableBlock(0)->Var("test2_out")->SetShape({32, 16, 128, 128}); |
181 |
| -// |
182 |
| -// auto& infer_inplace = OpInfoMap::Instance().Get(op->Type()).infer_inplace_; |
183 |
| -// auto in_to_outs = infer_inplace(*op); |
184 |
| -// EXPECT_EQ(in_to_outs.size(), 1ul); |
185 |
| -// auto it = in_to_outs.begin(); |
186 |
| -// EXPECT_EQ(it->first, "test2_a"); |
187 |
| -// EXPECT_EQ(it->second, "test2_out"); |
188 |
| -// } |
189 |
| -// |
190 |
| -// TEST(InferInplace, SingleGradOpInplaceInToOut) { |
191 |
| -// ProgramDesc prog; |
192 |
| -// auto* op = prog.MutableBlock(0)->AppendOp(); |
193 |
| -// op->SetType("single_op_grad"); |
194 |
| -// op->SetInput(GradVarName("Out"), {"test2_out"}); |
195 |
| -// op->SetOutput(GradVarName("X"), {"test2_a", "test2_b", "test2_c"}); |
196 |
| -// |
197 |
| -// prog.MutableBlock(0)->Var("test2_a")->SetType(proto::VarType::LOD_TENSOR); |
198 |
| -// prog.MutableBlock(0)->Var("test2_a")->SetShape({32, 16, 1024, 1024}); |
199 |
| -// prog.MutableBlock(0)->Var("test2_b")->SetType(proto::VarType::LOD_TENSOR); |
200 |
| -// prog.MutableBlock(0)->Var("test2_c")->SetType(proto::VarType::LOD_TENSOR); |
201 |
| -// prog.MutableBlock(0)->Var("test2_out"); |
202 |
| -// prog.MutableBlock(0)->Var("test2_out")->SetShape({32, 16, 1024, 1024}); |
203 |
| -// |
204 |
| -// auto& infer_inplace = OpInfoMap::Instance().Get(op->Type()).infer_inplace_; |
205 |
| -// auto in_to_outs = infer_inplace(*op); |
206 |
| -// EXPECT_EQ(in_to_outs.size(), 1ul); |
207 |
| -// auto it = in_to_outs.begin(); |
208 |
| -// EXPECT_EQ(it->first, "test2_out"); |
209 |
| -// EXPECT_EQ(it->second, "test2_a"); |
210 |
| -// } |
211 |
| -// |
212 |
| -// TEST(InferInplace, MultiOutInplaceInToOut) { |
213 |
| -// ProgramDesc prog; |
214 |
| -// auto* op = prog.MutableBlock(0)->AppendOp(); |
215 |
| -// op->SetType("multi_out_op"); |
216 |
| -// op->SetInput("X", {"a0", "a1"}); |
217 |
| -// op->SetInput("Y", {"b0"}); |
218 |
| -// op->SetInput("Z", {"c0", "c1"}); |
219 |
| -// op->SetOutput("Out", {"o0"}); |
220 |
| -// op->SetOutput("YOut", {"y0"}); |
221 |
| -// op->SetOutput("ZOut", {"z0"}); |
222 |
| -// |
223 |
| -// prog.MutableBlock(0)->Var("a0")->SetType(proto::VarType::LOD_TENSOR); |
224 |
| -// prog.MutableBlock(0)->Var("b0")->SetType(proto::VarType::LOD_TENSOR); |
225 |
| -// prog.MutableBlock(0)->Var("c0")->SetType(proto::VarType::LOD_TENSOR); |
226 |
| -// prog.MutableBlock(0)->Var("c1")->SetType(proto::VarType::LOD_TENSOR); |
227 |
| -// prog.MutableBlock(0)->Var("o0"); |
228 |
| -// prog.MutableBlock(0)->Var("y0"); |
229 |
| -// prog.MutableBlock(0)->Var("z0"); |
230 |
| -// prog.MutableBlock(0)->Var("a0")->SetShape({32, 16, 1024, 1024}); |
231 |
| -// prog.MutableBlock(0)->Var("b0")->SetShape({32, 16, 1024, 1024}); |
232 |
| -// prog.MutableBlock(0)->Var("c0")->SetShape({32, 16, 1024, 1024}); |
233 |
| -// prog.MutableBlock(0)->Var("o0")->SetShape({32, 16, 1024, 1024}); |
234 |
| -// prog.MutableBlock(0)->Var("y0")->SetShape({32, 16, 1024, 1024}); |
235 |
| -// prog.MutableBlock(0)->Var("z0")->SetShape({32, 16, 1024, 1024}); |
236 |
| -// |
237 |
| -// auto& infer_inplace = OpInfoMap::Instance().Get(op->Type()).infer_inplace_; |
238 |
| -// auto in_to_outs = infer_inplace(*op); |
239 |
| -// EXPECT_EQ(in_to_outs.size(), 3ul); |
240 |
| -// std::unordered_map<std::string, std::string> expects = { |
241 |
| -// {"a0", "o0"}, {"b0", "y0"}, {"c0", "z0"}, |
242 |
| -// }; |
243 |
| -// EXPECT_TRUE(expects == in_to_outs); |
244 |
| -// } |
245 |
| -// |
246 |
| -// TEST(InferInplace, MultiGradInplaceInToOut) { |
247 |
| -// ProgramDesc prog; |
248 |
| -// auto* op = prog.MutableBlock(0)->AppendOp(); |
249 |
| -// op->SetType("multi_out_grad"); |
250 |
| -// op->SetInput(GradVarName("Out"), {"o0"}); |
251 |
| -// op->SetInput(GradVarName("YOut"), {"y0"}); |
252 |
| -// op->SetInput(GradVarName("ZOut"), {"z0"}); |
253 |
| -// op->SetOutput(GradVarName("X"), {"a0", "a1"}); |
254 |
| -// op->SetOutput(GradVarName("Y"), {"b0"}); |
255 |
| -// op->SetOutput(GradVarName("Z"), {"c0", "c1"}); |
256 |
| -// |
257 |
| -// prog.MutableBlock(0)->Var("a0")->SetType(proto::VarType::LOD_TENSOR); |
258 |
| -// prog.MutableBlock(0)->Var("b0")->SetType(proto::VarType::LOD_TENSOR); |
259 |
| -// prog.MutableBlock(0)->Var("c0")->SetType(proto::VarType::LOD_TENSOR); |
260 |
| -// prog.MutableBlock(0)->Var("c1")->SetType(proto::VarType::LOD_TENSOR); |
261 |
| -// prog.MutableBlock(0)->Var("o0"); |
262 |
| -// prog.MutableBlock(0)->Var("y0"); |
263 |
| -// prog.MutableBlock(0)->Var("z0"); |
264 |
| -// prog.MutableBlock(0)->Var("a0")->SetShape({32, 16, 1024, 1024}); |
265 |
| -// prog.MutableBlock(0)->Var("b0")->SetShape({32, 16, 1024, 1024}); |
266 |
| -// prog.MutableBlock(0)->Var("c0")->SetShape({32, 16, 1024, 1024}); |
267 |
| -// prog.MutableBlock(0)->Var("o0")->SetShape({32, 16, 1024, 1024}); |
268 |
| -// prog.MutableBlock(0)->Var("y0")->SetShape({32, 16, 1024, 1024}); |
269 |
| -// prog.MutableBlock(0)->Var("z0")->SetShape({32, 16, 1024, 1024}); |
270 |
| -// |
271 |
| -// auto& infer_inplace = OpInfoMap::Instance().Get(op->Type()).infer_inplace_; |
272 |
| -// auto in_to_outs = infer_inplace(*op); |
273 |
| -// |
274 |
| -// EXPECT_EQ(in_to_outs.size(), 3ul); |
275 |
| -// std::unordered_map<std::string, std::string> expects = { |
276 |
| -// {"o0", "a0"}, {"y0", "b0"}, {"z0", "c0"}, |
277 |
| -// }; |
278 |
| -// EXPECT_TRUE(expects == in_to_outs); |
279 |
| -// } |
| 173 | +void FakeSuccData(ProgramDesc* prog) { // NOLINT |
| 174 | + prog->MutableBlock(0)->Var("test2_a")->SetType(proto::VarType::LOD_TENSOR); |
| 175 | + prog->MutableBlock(0)->Var("test2_a")->SetShape({32, 64, 128, 128}); |
| 176 | + prog->MutableBlock(0)->Var("test2_b")->SetType(proto::VarType::LOD_TENSOR); |
| 177 | + prog->MutableBlock(0)->Var("test2_c")->SetType(proto::VarType::LOD_TENSOR); |
| 178 | + prog->MutableBlock(0)->Var("test2_out"); |
| 179 | + prog->MutableBlock(0)->Var("test2_out")->SetShape({64, 32, 128, 128}); |
| 180 | +} |
| 181 | + |
| 182 | +void FakeNoInplaceData(ProgramDesc* prog) { // NOLINT |
| 183 | + prog->MutableBlock(0)->Var("test2_a")->SetType(proto::VarType::LOD_TENSOR); |
| 184 | + prog->MutableBlock(0)->Var("test2_a")->SetShape({32, 64, 128, 128}); |
| 185 | + prog->MutableBlock(0)->Var("test2_b")->SetType(proto::VarType::LOD_TENSOR); |
| 186 | + prog->MutableBlock(0)->Var("test2_c")->SetType(proto::VarType::LOD_TENSOR); |
| 187 | + prog->MutableBlock(0)->Var("test2_out"); |
| 188 | + prog->MutableBlock(0)->Var("test2_out")->SetShape({64, 31, 128, 128}); |
| 189 | +} |
| 190 | + |
| 191 | +ir::Node* GetNodeFromGraph(ir::Graph* g, std::string name) { |
| 192 | + ir::Node* op_node = nullptr; |
| 193 | + for (auto& item : g->Nodes()) { |
| 194 | + if (item->Name() == name) { |
| 195 | + op_node = item; |
| 196 | + break; |
| 197 | + } |
| 198 | + } |
| 199 | + return op_node; |
| 200 | +} |
| 201 | + |
| 202 | +std::unique_ptr<ir::Graph> test_SingleOpInplaceInToOut( |
| 203 | + std::unique_ptr<ir::Graph> g) { |
| 204 | + std::unique_ptr<details::InplacePass> pass(new details::InplacePass()); |
| 205 | + ir::Node* op_node = GetNodeFromGraph(g.get(), "single_op"); |
| 206 | + EXPECT_NE(op_node, nullptr); |
| 207 | + pass->Apply(g.get()); |
| 208 | + return g; |
| 209 | +} |
| 210 | + |
| 211 | +TEST(InferInplace, SingleOpInplaceInToOut) { |
| 212 | + ProgramDesc prog; |
| 213 | + auto* op = prog.MutableBlock(0)->AppendOp(); |
| 214 | + op->SetType("single_op"); |
| 215 | + op->SetInput("X", {"test2_a", "test2_b", "test2_c"}); |
| 216 | + op->SetOutput("Out", {"test2_out"}); |
| 217 | + |
| 218 | + FakeSuccData(&prog); |
| 219 | + std::unique_ptr<ir::Graph> g(new ir::Graph(prog)); |
| 220 | + g = test_SingleOpInplaceInToOut(std::move(g)); |
| 221 | + auto op_node = GetNodeFromGraph(g.get(), "single_op"); |
| 222 | + |
| 223 | + EXPECT_EQ(op_node->outputs[0]->Name(), "test2_a"); |
| 224 | +} |
| 225 | + |
| 226 | +TEST(InferInplace, SingleOpInplaceInToOutNoInplace) { |
| 227 | + ProgramDesc prog; |
| 228 | + auto* op = prog.MutableBlock(0)->AppendOp(); |
| 229 | + op->SetType("single_op"); |
| 230 | + op->SetInput("X", {"test2_a", "test2_b", "test2_c"}); |
| 231 | + op->SetOutput("Out", {"test2_out"}); |
| 232 | + |
| 233 | + FakeNoInplaceData(&prog); |
| 234 | + std::unique_ptr<ir::Graph> g(new ir::Graph(prog)); |
| 235 | + g = test_SingleOpInplaceInToOut(std::move(g)); |
| 236 | + auto op_node = GetNodeFromGraph(g.get(), "single_op"); |
| 237 | + |
| 238 | + EXPECT_EQ(op_node->outputs[0]->Name(), "test2_out"); |
| 239 | +} |
| 240 | + |
| 241 | +TEST(InferInplace, MultiOutInplaceInToOut) { |
| 242 | + ProgramDesc prog; |
| 243 | + auto* op = prog.MutableBlock(0)->AppendOp(); |
| 244 | + op->SetType("multi_out_op"); |
| 245 | + op->SetInput("X", {"a0", "a1"}); |
| 246 | + op->SetInput("Y", {"b0"}); |
| 247 | + op->SetInput("Z", {"c0", "c1"}); |
| 248 | + op->SetOutput("Out", {"o0"}); |
| 249 | + op->SetOutput("YOut", {"y0"}); |
| 250 | + op->SetOutput("ZOut", {"z0"}); |
| 251 | + |
| 252 | + prog.MutableBlock(0)->Var("a0")->SetType(proto::VarType::LOD_TENSOR); |
| 253 | + prog.MutableBlock(0)->Var("b0")->SetType(proto::VarType::LOD_TENSOR); |
| 254 | + prog.MutableBlock(0)->Var("c0")->SetType(proto::VarType::LOD_TENSOR); |
| 255 | + prog.MutableBlock(0)->Var("c1")->SetType(proto::VarType::LOD_TENSOR); |
| 256 | + prog.MutableBlock(0)->Var("o0"); |
| 257 | + prog.MutableBlock(0)->Var("y0"); |
| 258 | + prog.MutableBlock(0)->Var("z0"); |
| 259 | + prog.MutableBlock(0)->Var("a0")->SetShape({32, 16, 1024, 1024}); |
| 260 | + prog.MutableBlock(0)->Var("b0")->SetShape({32, 16, 1024, 1024}); |
| 261 | + prog.MutableBlock(0)->Var("c0")->SetShape({32, 16, 1024, 1024}); |
| 262 | + prog.MutableBlock(0)->Var("o0")->SetShape({32, 16, 1024, 1024}); |
| 263 | + prog.MutableBlock(0)->Var("y0")->SetShape({32, 16, 1024, 1024}); |
| 264 | + prog.MutableBlock(0)->Var("z0")->SetShape({32, 16, 1024, 1024}); |
| 265 | + |
| 266 | + std::unique_ptr<ir::Graph> g(new ir::Graph(prog)); |
| 267 | + std::unique_ptr<details::InplacePass> pass(new details::InplacePass()); |
| 268 | + pass->Apply(g.get()); |
| 269 | + auto op_node = GetNodeFromGraph(g.get(), "multi_out_op"); |
| 270 | + ASSERT_TRUE(op_node != nullptr); |
| 271 | + EXPECT_EQ(op_node->outputs[0]->Name(), "a0"); |
| 272 | + EXPECT_EQ(op_node->outputs[1]->Name(), "b0"); |
| 273 | + EXPECT_EQ(op_node->outputs[2]->Name(), "c0"); |
| 274 | +} |
| 275 | + |
| 276 | +TEST(InferInplace, MultiGradInplaceInToOut) { |
| 277 | + ProgramDesc prog; |
| 278 | + auto* op = prog.MutableBlock(0)->AppendOp(); |
| 279 | + op->SetType("multi_out_grad"); |
| 280 | + op->SetInput(GradVarName("Out"), {"o0"}); |
| 281 | + op->SetInput(GradVarName("YOut"), {"y0"}); |
| 282 | + op->SetInput(GradVarName("ZOut"), {"z0"}); |
| 283 | + op->SetOutput(GradVarName("X"), {"a0", "a1"}); |
| 284 | + op->SetOutput(GradVarName("Y"), {"b0"}); |
| 285 | + op->SetOutput(GradVarName("Z"), {"c0", "c1"}); |
| 286 | + |
| 287 | + prog.MutableBlock(0)->Var("a0")->SetType(proto::VarType::LOD_TENSOR); |
| 288 | + prog.MutableBlock(0)->Var("b0")->SetType(proto::VarType::LOD_TENSOR); |
| 289 | + prog.MutableBlock(0)->Var("c0")->SetType(proto::VarType::LOD_TENSOR); |
| 290 | + prog.MutableBlock(0)->Var("c1")->SetType(proto::VarType::LOD_TENSOR); |
| 291 | + prog.MutableBlock(0)->Var("o0"); |
| 292 | + prog.MutableBlock(0)->Var("y0"); |
| 293 | + prog.MutableBlock(0)->Var("z0"); |
| 294 | + prog.MutableBlock(0)->Var("a0")->SetShape({32, 16, 1024, 1024}); |
| 295 | + prog.MutableBlock(0)->Var("b0")->SetShape({32, 16, 1024, 1024}); |
| 296 | + prog.MutableBlock(0)->Var("c0")->SetShape({32, 16, 1024, 1024}); |
| 297 | + prog.MutableBlock(0)->Var("o0")->SetShape({32, 16, 1024, 1024}); |
| 298 | + prog.MutableBlock(0)->Var("y0")->SetShape({32, 16, 1024, 1024}); |
| 299 | + prog.MutableBlock(0)->Var("z0")->SetShape({32, 15, 1024, 1024}); |
| 300 | + |
| 301 | + std::unique_ptr<ir::Graph> g(new ir::Graph(prog)); |
| 302 | + std::unique_ptr<details::InplacePass> pass(new details::InplacePass()); |
| 303 | + pass->Apply(g.get()); |
| 304 | + auto op_node = GetNodeFromGraph(g.get(), "multi_out_grad"); |
| 305 | + ASSERT_TRUE(op_node != nullptr); |
| 306 | + EXPECT_EQ(op_node->outputs[0]->Name(), "o0"); |
| 307 | + EXPECT_EQ(op_node->outputs[2]->Name(), "y0"); |
| 308 | + EXPECT_EQ(op_node->outputs[3]->Name(), "c0"); |
| 309 | + |
| 310 | + std::unordered_map<std::string, std::string> expects = { |
| 311 | + {"o0", "a0"}, {"y0", "b0"}, {"z0", "c0"}, |
| 312 | + }; |
| 313 | +} |
280 | 314 |
|
281 | 315 | } // namespace framework
|
282 | 316 | } // namespace paddle
|
0 commit comments