()
| 339 | # Integration test for offloading in a realistic scenario |
| 340 | @pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA not available") |
| 341 | def test_offloading_integration(): |
| 342 | device = torch.device('cuda') |
| 343 | # Create a mini model with 4 blocks |
| 344 | model = SimpleModel(5) |
| 345 | model.to(device) |
| 346 | blocks = model.blocks |
| 347 | |
| 348 | # Initialize model offloader |
| 349 | offloader = ModelOffloader( |
| 350 | blocks=blocks, |
| 351 | blocks_to_swap=2, |
| 352 | device=device, |
| 353 | debug=True |
| 354 | ) |
| 355 | |
| 356 | # Prepare blocks for forward pass |
| 357 | offloader.prepare_block_devices_before_forward(blocks) |
| 358 | |
| 359 | # Simulate forward pass with offloading |
| 360 | input_tensor = torch.randn(1, 10, device=device) |
| 361 | x = input_tensor |
| 362 | |
| 363 | for i, block in enumerate(blocks): |
| 364 | # Wait for the current block to be ready |
| 365 | offloader.wait_for_block(i) |
| 366 | |
| 367 | # Process through the block |
| 368 | x = block(x) |
| 369 | |
| 370 | # Schedule moving weights for future blocks |
| 371 | offloader.submit_move_blocks(blocks, i) |
| 372 | |
| 373 | # Verify we get a valid output |
| 374 | assert x.shape == (1, 10) |
| 375 | assert not torch.isnan(x).any() |
| 376 | |
| 377 | |
| 378 | # Error handling tests |
nothing calls this directly
no test coverage detected