Skip to content

Latest commit

 

History

History
254 lines (187 loc) · 10.5 KB

CONTRIBUTING.md

File metadata and controls

254 lines (187 loc) · 10.5 KB

Contributing guidelines

Pull Request Checklist

Before sending your pull requests, make sure you followed this list.

  1. Read these Guidelines in full.

  2. Please take a look at the LICENSE (it's Apache 2.0).

  3. Make sure you sign your commits. E.g. use git commit -s when commiting.

  4. Check your changes are consistent with the Standards and Coding Style.

  5. Make sure all unittests finish successfully before sending PR.

  6. Send your Pull Request to the master branch

How to become a contributor and submit your own code

Signing your commits

Before we can take your patches we need to take care of legal concerns.

Please sign each commits using git commit -s. In case you forgot to sign previous commits you can amend previous commits using:

  • git commit -s --amend for the last commit.
  • git rebase --signoff for all the commits of your pull request.

Contributing code

Contributions are welcome! You can send us pull requests to help improve Kaolin, if you are just getting started, Gitlab has a how to.

Kaolin team members will be assigned to review your pull requests. Once they your change passes the review and the continuous integration checks, a Kaolin member will approve and merge them to the repository.

If you want to contribute, Gitlab issues are a good starting point, especially the ones with the label good first issue. If you started working on a issue, leave a comment so other people know that you're working on it, you can also coordinate with others on the issue comment threads.

Standards and Coding Style

General guidelines

  • New features must include unit tests which help guarantee correctness in the present and future.
  • API changes should be minimal and backward compatible. Any changes that break backward compatibility should be carefully considered and tracked so that they can be included in the release notes.
  • New features may not accepted if the cost of maintenance is too high in comparison of its benefit, they may also be integrated to contrib subfolders for minimal support and maintenance before eventually being integrated to the core.

License

Include a license at the top of new files.

C/C++/CUDA
// Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES.
// All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//    http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Python
# Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

When non-trivial changes are made, the license should be changed accordingly. For instance, if the file is originally authored in 2021, a few typos get fixed in 202, a paragraph or subroutine is added in 2023, and a major rev2.0 is created in 2024, you would in 2024 write: "Copyright (c) 2021,23-24 NVIDIA CORPORATION & AFFILIATES"

Code organization

  • kaolin - The core Kaolin library, comprised of python modules, except for code under csrc or experimental.
    • csrc - Directory for all the C++ / CUDA implementations of custom ops. The gpu ops parts will be under the subdirectory csrc/cuda while the cpu parts will be under the subdirectory csrc/cpu.
    • io - Module of all the I/O features of Kaolin, such a importing and exporting 3D models.
    • metrics - Module of all the metrics that can be used as differentiable loss or distance.
    • ops - Module of all the core operations of kaolin on different 3D representations.
    • render - Module of all the differentiable renderers modules and advanced implementations.
    • utils - Module of all the utility features for debugging and testing.
    • visualize - Module of all the visualization modules.
    • experimental - Contains less thoroughly tested components for early adoption.
  • examples - Examples of Kaolin usage
  • tests - Tests for all Kaolin

C++ coding style

We follow Google C++ Style Guide, with exception on naming for functions / methods, where we use snake_case.

Files structure should be:

  • *.cuh files are for reusable device functions (using static inline __device__ for definition)
// file is kaolin/csrc/ops/add.cuh

#ifndef KAOLIN_OPS_ADD_CUH_
#define KAOLIN_OPS_ADD_CUH_

namespace kaolin {

static inline __device__ float add(float a, float b) {
  return a + b;
}

static inline __device__ double add(double a, double b) {
  return a + b;
}

}  // namespace kaolin

#endif  // KAOLIN_OPS_ADD_CUH_
  • *.cpp files (except specific files like bindings.cpp) should be used for defining the functions that will be directly binded to python, those functions should only be responsible for checking inputs device / memory layout / size, generating output (if possible) and call the base function in the _cuda.cu or _cpu.cpp. The kernel launcher should be declared at the beginning of the file or from an included header (if reused).
// file is kaolin/csrc/ops/foo.cpp

#include <ATen/ATen.h>

namespace kaolin {

#if WITH_CUDA
void foo_cuda_impl(
    at::Tensor lhs,
    at::Tensor rhs,
    at::Tensor output);
#endif  // WITH_CUDA

at::Tensor foo_cuda(
    at::Tensor lhs,
    at::Tensor rhs) {
  at::TensorArg lhs_arg{lhs, "lhs", 1}, rhs_arg{rhs, "rhs", 2};
  at::checkSameGPU("foo_cuda", lhs_arg, rhs_arg);
  at::checkAllContiguous("foo_cuda", {lhs_arg, rhs_arg});
  at::checkSameSize("foo_cuda", lhs_arg, rhs_arg);
  at::checkSameType("foo_cuda", lhs_arg, rhs_arg);

  at::Tensor output = at::zeros_like(lhs);

#if WITH_CUDA
  foo_cuda_impl(lhs, rhs, output);

#else
  KAOLIN_NO_CUDA_ERROR(__func__);
#endif  // WITH_CUDA
  return output;
}

}  // namespace kaolin
  • *_cuda.cu files are for dispatching given the inputs types and implementing the operations on GPU, by using the Torch C++ API and/or launching a custom cuda kernel.
// file is kaolin/csrc/ops/foo_cuda.cu

#include <ATen/ATen.h>
#include <c10/cuda/CUDAGuard.h>
#include "./add.cuh"

namespace kaolin {

template<typename scalar_t>
__global__
void foo_cuda_kernel(
    const scalar_t* __restrict__ lhs,
    const scalar_t* __restrict__ rhs,
    const int numel,
    scalar_t* __restrict__ output) {
  for (int i = threadIdx.x + blockIdx.x * blockDim.x;
       i < numel; i++) {
    output[i] = add(lhs[i], rhs[i]);
  }
}

void foo_cuda_impl(
    at::Tensor lhs,
    at::Tensor rhs,
    at::Tensor output) {
  const int threads = 1024;
  const int blocks = 64;
  AT_DISPATCH_FLOATING_TYPES(lhs.scalar_type(), "foo_cuda", [&] {
    const at::cuda::OptionalCUDAGuard device_guard(at::device_of(output));
    auto stream = at::cuda::getCurrentCUDAStream();
    foo_cuda_kernel<<<blocks, threads, 0, stream>>>(
        lhs.data_ptr<scalar_t>(),
        rhs.data_ptr<scalar_t>(),
        lhs.numel(),
        output.data_ptr<scalar_t>());
  });
}

}  // namespace kaolin
  • *.h files are for declaring functions that will be binded to Python, those header files are to be included in bindings.cpp.
// file is kaolin/csrc/ops/foo.h

#ifndef KAOLIN_OPS_FOO_H_
#define KAOLIN_OPS_FOO_H_

#include <ATen/ATen.h>

namespace kaolin {

at::Tensor foo_cuda(
    at::Tensor lhs,
    at::Tensor rhs);

}  // namespace kaolin

#endif  // KAOLIN_OPS_FOO_H_

Python coding style

We follow PEP8 Style Guide with some exceptions listed in flake8 config file and generally follow PyTorch naming conventions.

It is enforced using flake8, with flake8-bugbear, flake8-comprehensions, flake8-mypy and flake8-pyi

To run flake8 execute flake8 --config=.flake8 . from the root of kaolin.

On top of that we use prefixes (packed\_, padded\_) to indicate that a module / op is specific to a layout, an , all ops of the same purpose for different layouts should be in the same file.

tests/python/kaolin/ should follows the same directory structure of kaolin/. E.g. each module kaolin/path/to/mymodule.py should have a corresponding tests/python/kaolin/path/to/test_mymodule.py.

Tests

We are applying pytest on tests/python directory, with pytest-cov, which should follows the directory structure of kaolin. To run these tests execute pytest --cov=kaolin/ tests/ from the root of kaolin.

Additional integration tests are located in tests/integration. See that subdirectory for details.

Documentation

Contributors are encouraged to verify the generated documentation before each pull request.

To build your own documentation, follow the guide.