"applications/Colossal-LLaMA-2/docs/example_7b.md" did not exist on "74aa7d964a8fbb9a9a4865ecd9ac2bda817c3ef2"
test_complete_workflow.py 2.63 KB
Newer Older
1
2
from functools import partial

3
import pytest
4
import torch
5
import torch.distributed as dist
6
7
8
9
import torch.multiprocessing as mp
import torch.nn as nn

import colossalai
10
11
12
from colossalai.fx import ColoTracer
from colossalai.fx.passes.shard_1d_pass import transformer_mlp_pass
from colossalai.tensor import ProcessGroup
13
14
15
from colossalai.testing import rerun_if_address_is_in_use
from colossalai.utils import free_port
from colossalai.utils.model.lazy_init_context import LazyInitContext
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


class MLP(torch.nn.Module):

    def __init__(self, dim: int):
        super().__init__()
        self.linear1 = torch.nn.Linear(dim, dim)
        self.linear2 = torch.nn.Linear(dim, dim)
        self.dropout = torch.nn.Dropout(0)
        self.relu = torch.nn.ReLU()

    def forward(self, x):
        x = self.linear1(x)
        x = self.dropout(x)
        x = self.relu(x)
        x = self.linear2(x)
        return x


35
def run_workflow(world_size, dev):
36
37
38
39
    # initailization
    with LazyInitContext() as ctx:
        model = MLP(16)

40
41
42
    for param in model.parameters():
        assert param.is_meta

43
44
45
46
47
48
    # tracing
    tracer = ColoTracer()
    graph = tracer.trace(model)
    gm = torch.fx.GraphModule(model, graph, model.__class__.__name__)

    # annotate
49
    annotated_gm = transformer_mlp_pass(gm, process_group=ProcessGroup(tp_degree=world_size))
50
51
52
    annotated_gm.recompile()

    # materialization and sharding
53
    ctx.lazy_init_parameters(annotated_gm, device=dev)
54
55
    for param in model.parameters():
        assert not param.is_meta
56
57
58
59
60
61
62
63

    # # check sharding
    assert list(model.linear1.weight.shape) == [16 // world_size, 16]
    assert list(model.linear1.bias.shape) == [16 // world_size]
    assert list(model.linear2.weight.shape) == [16, 16 // world_size]

    # test forward to make sure that IR transform will produce the same results
    # like how ColoTensor would do it normally
64
    data = torch.rand(4, 16, device=dev)
65
66
    non_fx_out = model(data)
    fx_out = annotated_gm(data)
67
    assert torch.equal(non_fx_out, fx_out), f'{non_fx_out} vs {fx_out}'
68
69


70
def run_dist(rank, world_size, dev, port):
71
    colossalai.launch(config={}, rank=rank, world_size=world_size, host='localhost', port=port, backend='nccl')
72
    run_workflow(world_size, dev)
73
74
75
76


@pytest.mark.dist
@pytest.mark.parametrize('world_size', [1, 2])
77
@pytest.mark.parametrize('dev', ['cuda', 'cpu'])
78
@rerun_if_address_is_in_use()
79
80
81
82
def test_complete_workflow(world_size, dev):
    if dev == 'cpu' and world_size > 1:
        return
    run_func = partial(run_dist, world_size=world_size, dev=dev, port=free_port())
83
84
85
86
    mp.spawn(run_func, nprocs=world_size)


if __name__ == '__main__':
87
    test_complete_workflow(1, 'cuda')