Skip to content

feat: Add initial support for CUDA #433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/Development.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [Stacktraces](#stacktraces)
- [Attaching a debugger](#attaching-a-debugger)
- [Debugging on Linux](#debugging-on-linux)
- [Testing CUDA/NVCC support](#testing-cudanvcc-support)
- [Inspecting Clang ASTs](#inspecting-clang-asts)
- [Automated test case reduction](#automated-test-case-reduction)
- [Debugging preprocessor issues](#debugging-preprocessor-issues)
Expand Down Expand Up @@ -162,6 +163,14 @@ There is a [VM setup script](/tools/vm-setup.sh) available
to configure a GCP VM for building scip-clang.
We recommend using Ubuntu 20.04+ with 16 cores or more.

#### Testing CUDA/NVCC support

There is a [CUDA-specific VM setup script](/tools/vm-setup-cuda.sh)
which installs the CUDA SDK. Use it in a GCP VM
which has a GPU attached.

You may need to restart your shell for changes to take effect.

### Inspecting Clang ASTs

Print the AST nodes:
Expand Down
23 changes: 23 additions & 0 deletions docs/IndexingProjects.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [Redpanda](#redpanda)
- [Postgres](#postgres)
- [Boost](#boost)
- [Apache MXNet](#apache-mxnet)

## scip-clang

Expand Down Expand Up @@ -224,3 +225,25 @@ for d in dirs:
print("Indexing failed for {}; skipping upload".format(d))
continue
```

## Apache MXNet

Apache MXNet is an interesting project to test because
it has over 100 CUDA files.

The indexing steps below are based on the [official instructions](https://mxnet.apache.org/versions/1.9.1/get_started/build_from_source.html).

```
git clone --recursive https://github.com/apache/mxnet
cd mxnet
sudo apt-get update
sudo apt-get install -y build-essential git ninja-build ccache libopenblas-dev libopencv-dev cmake gfortran clang++-14 clang libomp-dev
```

```
cmake -B build -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DUSE_CUDA=ON

cat build/compile_commands.json | jq --arg rdir "$(clang -print-resource-dir)" 'map(if .command | contains("nvcc") then .command += " -resource-dir " + $rdir else . end)' > build/modified.json

scip-clang --compdb-path build/modified.json
```
55 changes: 52 additions & 3 deletions indexer/CompilationDatabase.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,38 @@ struct GccToolchainInfo : ToolchainInfo {
}
};

struct NvccToolchainInfo : ToolchainInfo {
scip_clang::AbsolutePath cudaDir;

NvccToolchainInfo(scip_clang::AbsolutePath cudaDir)
: ToolchainInfo(), cudaDir(cudaDir) {}

virtual CompilerKind kind() const override {
return CompilerKind::Nvcc;
}

virtual bool isWellFormed() const override {
auto path = scip_clang::joinPath(cudaDir.asStringRef(), "include");
if (!std::filesystem::exists(path)) {
spdlog::error(
"directory '{}' does not exist; expected to find CUDA SDK headers"
" there because nvcc was found at {}",
path,
scip_clang::joinPath(cudaDir.asStringRef(),
scip_clang::joinPath("bin", "nvcc")));
return false;
}
return true;
}

virtual void
adjustCommandLine(std::vector<std::string> &commandLine) const override {
commandLine.push_back(
fmt::format("-isystem{}{}include", this->cudaDir.asStringRef(),
std::filesystem::path::preferred_separator));
}
};

} // namespace

static CompletedProcess runProcess(std::vector<std::string> &args,
Expand Down Expand Up @@ -231,7 +263,20 @@ ToolchainInfo::infer(const scip_clang::AbsolutePath &compilerPath) {
findSearchDirsInvocation);
}

spdlog::warn("compiler at '{}' is not one of clang/clang++/gcc/g++",
std::vector<std::string> argv = {compilerPath.asStringRef(), "--version"};
auto compilerVersionResult = ::runProcess(argv, "checking for NVCC");
if (compilerVersionResult.isSuccess()
&& !compilerVersionResult.stdoutLines.empty()
&& absl::StrContains(compilerVersionResult.stdoutLines[0], "NVIDIA")) {
if (auto binDir = compilerPath.asRef().prefix()) {
if (auto cudaDir = binDir->prefix()) {
return std::make_unique<NvccToolchainInfo>(
scip_clang::AbsolutePath(*cudaDir));
}
}
}

spdlog::warn("compiler at '{}' is not one of clang/clang++/gcc/g++/nvcc",
compilerPath.asStringRef());
noteStdlib();
return failure;
Expand Down Expand Up @@ -693,8 +738,12 @@ void ResumableParser::initialize(compdb::File compdb, ParseOptions options) {
this->reader.IterativeParseInit();
this->options = options;
std::vector<std::string> extensions;
// Via https://stackoverflow.com/a/3223792/2682729
for (auto ext : {"c", "C", "cc", "cpp", "CPP", "cxx", "c++"}) {
// clang-format off
// Via https://stackoverflow.com/a/3223792/2682729 (for C and C++)
// For CUDA, see https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#basics-cdp1
// and https://github.com/github-linguist/linguist/blob/master/lib/linguist/languages.yml#L1342-L1346
// clang-format on
for (auto ext : {"c", "C", "cc", "cpp", "CPP", "cxx", "c++", "cu"}) {
extensions.emplace_back(llvm::Regex::escape(fmt::format(".{}", ext)));
};
this->fileExtensionRegex =
Expand Down
1 change: 1 addition & 0 deletions indexer/CompilationDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class CommandObjectHandler
enum class CompilerKind {
Gcc,
Clang,
Nvcc,
};

struct ToolchainInfo {
Expand Down
24 changes: 24 additions & 0 deletions tools/vm-setup-cuda.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
rm -rf cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get -y install cuda

ZSH_INIT="$HOME/.zshrc"
if [ -f "$ZSH_INIT" ] && ! grep -q "cuda" "$ZSH_INIT"; then
echo 'export PATH="/usr/local/cuda/bin:$PATH"' >> "$ZSH_INIT"
echo "Added CUDA path to $ZSH_INIT"
fi

BASH_INIT="$HOME/.bashrc"
if [ -f "$BASH_INIT" ] && ! grep -q "cuda" "$BASH_INIT"; then
echo 'export PATH="/usr/local/cuda/bin:$PATH"' >> "$BASH_INIT"
echo "Added CUDA path to $BASH_INIT"
fi

FISH_INIT="$HOME/.config/fish/config.fish"
if [ -f "$FISH_INIT" ] && ! grep -q "cuda" "$FISH_INIT"; then
echo "fish_add_path /usr/local/cuda/bin" >> "$FISH_INIT"
echo "Added CUDA path to $FISH_INIT"
fi