diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db180c3c2..1b068c227 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: - name: Linting run: pre-commit run --all-files - name: Format c/cuda codes with clang-format - uses: DoozyX/clang-format-lint-action@v0.6 + uses: DoozyX/clang-format-lint-action@v0.11 with: source: mmcv/ops/csrc extensions: h,c,cpp,hpp,cu,cuh @@ -42,11 +42,9 @@ jobs: - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y ffmpeg libturbojpeg - name: Install unittest dependencies - run: pip install pytest coverage lmdb PyTurboJPEG + run: pip install -r requirements/test.txt - name: Build and install run: rm -rf .eggs && pip install -e . - - name: Install Pillow - run: pip install Pillow - name: Run unittests and generate coverage report run: | pytest tests/ --ignore=tests/test_runner --ignore=tests/test_optimizer.py --ignore=tests/test_cnn --ignore=tests/test_parallel.py --ignore=tests/test_ops --ignore=tests/test_load_model_zoo.py --ignore=tests/test_utils/test_logging.py --ignore=tests/test_image/test_io.py --ignore=tests/test_utils/test_registry.py @@ -58,10 +56,10 @@ jobs: strategy: matrix: python-version: [3.7] - torch: [1.6.0] + torch: [1.7.0] include: - - torch: 1.6.0 - torchvision: 0.7.0 + - torch: 1.7.0 + torchvision: 0.8.1 steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -70,13 +68,10 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y ffmpeg libturbojpeg - - name: Install Pillow - run: pip install Pillow==6.2.2 - if: ${{matrix.torchvision == '0.4.2'}} - name: Install PyTorch run: pip install torch==${{matrix.torch}}+cpu torchvision==${{matrix.torchvision}}+cpu -f https://download.pytorch.org/whl/torch_stable.html - name: Install unittest dependencies - run: pip install pytest coverage lmdb PyTurboJPEG + run: pip install -r requirements/test.txt - name: Build and install run: rm -rf .eggs && pip install -e . - name: Run unittests @@ -87,7 +82,7 @@ jobs: strategy: matrix: python-version: [3.7] - torch: [1.3.1, 1.4.0, 1.5.1, 1.6.0] + torch: [1.3.1, 1.4.0, 1.5.1, 1.6.0, 1.7.0] include: - torch: 1.3.1 torchvision: 0.4.2 @@ -97,6 +92,8 @@ jobs: torchvision: 0.6.1 - torch: 1.6.0 torchvision: 0.7.0 + - torch: 1.7.0 + torchvision: 0.8.1 steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -111,7 +108,7 @@ jobs: - name: Install PyTorch run: pip install torch==${{matrix.torch}}+cpu torchvision==${{matrix.torchvision}}+cpu -f https://download.pytorch.org/whl/torch_stable.html - name: Install unittest dependencies - run: pip install pytest coverage lmdb PyTurboJPEG onnx==1.6.0 onnxruntime==1.2.0 + run: pip install -r requirements/test.txt - name: Build and install run: rm -rf .eggs && pip install -e . - name: Run unittests and generate coverage report @@ -131,7 +128,7 @@ jobs: strategy: matrix: python-version: [3.7] - torch: [1.3.1, 1.5.1+cu101, 1.6.0+cu101] + torch: [1.3.1, 1.5.1+cu101, 1.6.0+cu101, 1.7.0+cu101] include: - torch: 1.3.1 torchvision: 0.4.2 @@ -139,12 +136,14 @@ jobs: torchvision: 0.6.1+cu101 - torch: 1.6.0+cu101 torchvision: 0.7.0+cu101 + - torch: 1.7.0+cu101 + torchvision: 0.8.1+cu101 - python-version: 3.6 - torch: 1.6.0+cu101 - torchvision: 0.7.0+cu101 + torch: 1.7.0+cu101 + torchvision: 0.8.1+cu101 - python-version: 3.8 - torch: 1.6.0+cu101 - torchvision: 0.7.0+cu101 + torch: 1.7.0+cu101 + torchvision: 0.8.1+cu101 steps: - uses: actions/checkout@v2 @@ -176,7 +175,7 @@ jobs: - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y ffmpeg libturbojpeg - name: Install unittest dependencies - run: pip install pytest coverage lmdb PyTurboJPEG + run: pip install -r requirements/test.txt - name: Build and install run: rm -rf .eggs && pip install -e . - name: Run unittests and generate coverage report @@ -184,10 +183,10 @@ jobs: coverage run --branch --source=mmcv -m pytest tests/ --ignore=tests/test_ops/test_onnx.py coverage xml coverage report -m - # Only upload coverage report for python3.7 && pytorch1.5 + # Only upload coverage report for python3.7 && pytorch1.6 - name: Upload coverage to Codecov - if: ${{matrix.torch == '1.5.1+cu101' && matrix.python-version == '3.7'}} - uses: codecov/codecov-action@v1.0.10 + if: ${{matrix.torch == '1.6.0+cu101' && matrix.python-version == '3.7'}} + uses: codecov/codecov-action@v1.0.14 with: file: ./coverage.xml flags: unittests @@ -199,7 +198,7 @@ jobs: runs-on: macos-latest strategy: matrix: - torch: [1.3.1, 1.5.1, 1.6.0] + torch: [1.3.1, 1.5.1, 1.6.0, 1.7.0] include: - torch: 1.3.1 torchvision: 0.4.2 @@ -207,6 +206,8 @@ jobs: torchvision: 0.6.1 - torch: 1.6.0 torchvision: 0.7.0 + - torch: 1.7.0 + torchvision: 0.8.1 steps: - uses: actions/checkout@v2 - name: Set up Python 3.7 @@ -216,12 +217,10 @@ jobs: - name: Install system dependencies run: brew install ffmpeg jpeg-turbo - name: Install unittest dependencies - run: pip install pytest coverage lmdb PyTurboJPEG + run: pip install -r requirements/test.txt - name: Install Pillow run: pip install Pillow==6.2.2 if: ${{matrix.torchvision == '0.4.2'}} - - name: Install ONNX - run: pip install onnx==1.6.0 onnxruntime==1.2.0 - name: Install PyTorch run: pip install torch==${{matrix.torch}} torchvision==${{matrix.torchvision}} --no-cache-dir - name: Build and install diff --git a/.readthedocs.yml b/.readthedocs.yml index 8bef1b0ae..5bb171afa 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,5 +3,5 @@ version: 2 python: version: 3.7 install: - - requirements: requirements.txt - - requirements: docs/requirements.txt + - requirements: requirements/runtime.txt + - requirements: requirements/docs.txt diff --git a/MANIFEST.in b/MANIFEST.in index dc9dca578..a233249c2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ include mmcv/video/optflow_warp/*.hpp mmcv/video/optflow_warp/*.pyx -include requirements.txt +include requirements/runtime.txt include mmcv/model_zoo/open_mmlab.json mmcv/model_zoo/deprecated.json mmcv/model_zoo/mmcls.json include mmcv/ops/csrc/*.cuh mmcv/ops/csrc/*.hpp include mmcv/ops/csrc/pytorch/*.cu mmcv/ops/csrc/pytorch/*.cpp diff --git a/mmcv/cnn/bricks/wrappers.py b/mmcv/cnn/bricks/wrappers.py index 9ad778c18..899e816ac 100644 --- a/mmcv/cnn/bricks/wrappers.py +++ b/mmcv/cnn/bricks/wrappers.py @@ -84,8 +84,8 @@ class ConvTranspose2d(nn.ConvTranspose2d): class MaxPool2d(nn.MaxPool2d): def forward(self, x): - # PyTorch 1.6 does not support empty tensor inference yet - if x.numel() == 0 and obsolete_torch_version(TORCH_VERSION, (1, 6)): + # PyTorch 1.7 does not support empty tensor inference yet + if x.numel() == 0 and obsolete_torch_version(TORCH_VERSION, (1, 7)): out_shape = list(x.shape[:2]) for i, k, p, s, d in zip(x.shape[-2:], _pair(self.kernel_size), _pair(self.padding), _pair(self.stride), diff --git a/docs/requirements.txt b/requirements/docs.txt similarity index 100% rename from docs/requirements.txt rename to requirements/docs.txt diff --git a/requirements/runtime.txt b/requirements/runtime.txt new file mode 100644 index 000000000..dc98a65c1 --- /dev/null +++ b/requirements/runtime.txt @@ -0,0 +1,6 @@ +addict +numpy +Pillow +pyyaml +regex;sys_platform=='win32' +yapf diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 000000000..e26c84613 --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1,6 @@ +coverage +lmdb +onnx==1.7.0 +onnxruntime==1.4.0 +pytest +PyTurboJPEG diff --git a/setup.py b/setup.py index 7a6071dae..84b1173c1 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def get_version(): return locals()['__version__'] -def parse_requirements(fname='requirements.txt', with_version=True): +def parse_requirements(fname='requirements/runtime.txt', with_version=True): """Parse the package dependencies listed in a requirements file but strips specific versioning information. diff --git a/tests/test_cnn/test_wrappers.py b/tests/test_cnn/test_wrappers.py index 755970c6a..283520d1a 100644 --- a/tests/test_cnn/test_wrappers.py +++ b/tests/test_cnn/test_wrappers.py @@ -169,7 +169,7 @@ def test_linear(): wrapper(x_empty) -@patch('mmcv.cnn.bricks.wrappers.TORCH_VERSION', (1, 7)) +@patch('mmcv.cnn.bricks.wrappers.TORCH_VERSION', (1, 8)) def test_nn_op_forward_called(): for m in ['Conv2d', 'ConvTranspose2d', 'MaxPool2d']: diff --git a/tests/test_ops/test_onnx.py b/tests/test_ops/test_onnx.py index e0bc7a4ac..c2e7beb33 100644 --- a/tests/test_ops/test_onnx.py +++ b/tests/test_ops/test_onnx.py @@ -20,43 +20,39 @@ class WrapFunction(nn.Module): return self.wrapped_function(*args, **kwargs) -class Testonnx(object): +def test_nms(): + from mmcv.ops import nms + np_boxes = np.array([[6.0, 3.0, 8.0, 7.0], [3.0, 6.0, 9.0, 11.0], + [3.0, 7.0, 10.0, 12.0], [1.0, 4.0, 13.0, 7.0]], + dtype=np.float32) + np_scores = np.array([0.6, 0.9, 0.7, 0.2], dtype=np.float32) + boxes = torch.from_numpy(np_boxes) + scores = torch.from_numpy(np_scores) + pytorch_dets, _ = nms(boxes, scores, iou_threshold=0.3, offset=0) + pytorch_score = pytorch_dets[:, 4] + nms = partial(nms, iou_threshold=0.3, offset=0) + wrapped_model = WrapFunction(nms) + wrapped_model.cpu().eval() + with torch.no_grad(): + torch.onnx.export( + wrapped_model, (boxes, scores), + onnx_file, + export_params=True, + keep_initializers_as_inputs=True, + input_names=['boxes', 'scores'], + opset_version=11) + onnx_model = onnx.load(onnx_file) - def test_nms(self): - from mmcv.ops import nms - np_boxes = np.array([[6.0, 3.0, 8.0, 7.0], [3.0, 6.0, 9.0, 11.0], - [3.0, 7.0, 10.0, 12.0], [1.0, 4.0, 13.0, 7.0]], - dtype=np.float32) - np_scores = np.array([0.6, 0.9, 0.7, 0.2], dtype=np.float32) - boxes = torch.from_numpy(np_boxes) - scores = torch.from_numpy(np_scores) - pytorch_dets, _ = nms(boxes, scores, iou_threshold=0.3, offset=0) - pytorch_score = pytorch_dets[:, 4] - nms = partial(nms, iou_threshold=0.3, offset=0) - wrapped_model = WrapFunction(nms) - wrapped_model.cpu().eval() - with torch.no_grad(): - torch.onnx.export( - wrapped_model, (boxes, scores), - onnx_file, - export_params=True, - keep_initializers_as_inputs=True, - input_names=['boxes', 'scores'], - opset_version=11) - onnx_model = onnx.load(onnx_file) - - # get onnx output - input_all = [node.name for node in onnx_model.graph.input] - input_initializer = [ - node.name for node in onnx_model.graph.initializer - ] - net_feed_input = list(set(input_all) - set(input_initializer)) - assert (len(net_feed_input) == 2) - sess = rt.InferenceSession(onnx_file) - onnx_dets, _ = sess.run(None, { - 'scores': scores.detach().numpy(), - 'boxes': boxes.detach().numpy() - }) - onnx_score = onnx_dets[:, 4] - os.remove(onnx_file) - assert np.allclose(pytorch_score, onnx_score, atol=1e-3) + # get onnx output + input_all = [node.name for node in onnx_model.graph.input] + input_initializer = [node.name for node in onnx_model.graph.initializer] + net_feed_input = list(set(input_all) - set(input_initializer)) + assert (len(net_feed_input) == 2) + sess = rt.InferenceSession(onnx_file) + onnx_dets, _ = sess.run(None, { + 'scores': scores.detach().numpy(), + 'boxes': boxes.detach().numpy() + }) + onnx_score = onnx_dets[:, 4] + os.remove(onnx_file) + assert np.allclose(pytorch_score, onnx_score, atol=1e-3)