Feature: Passing arguments to NVCC compiler (#26)

* Add option to give nvcc extra arguments

* Add test for nvcc options that changes c++ dialect from c++17 to c++14

* Add make and the english language pack to devcontainer to be able to build the documentation

* Update documentation config to automatically import the current version of the package

* Document new --compiler-args argument

* Improve tests coverage by testing for bad arguments and the error output during a failed compilation

* Add IPython to docs requirements to allow the __version__ import for readthedocs env

* Change devcontainer base image to have the latest CUDA toolkit

* Mock the nsight compute tool with a bash script

* Add test to compile with opencv

* Add new page to documentation that contains a new notebook that explains compiling with external libraries

* Add autodocstring vscode extension to devcontainer

* Add function that modifies the default profiler/compiler arguments to allow reusing them in multiple magic command calls

* Update pylint exceptions

* Update contributing instructions

* Change version from 1.0.3 to 1.1.0 due to adding features in a backward-compatible manner

* Install latest CUDA toolkit on the test runner to pass the OpenCV compilation test

* Install opencv in test runner and update code coverage install

* Add CUDA bin to PATH in test and coverage runners

* Add cuda bin to path variable in .bashrc

* Update way to set environment variable PATH in github action

* Change devcontainer base image back to ubuntu:22.04 to match the environment from the test runner
This commit is contained in:
Cosmin Ștefan Ciocan
2024-02-12 17:29:26 +01:00
committed by GitHub
parent 5cd225851b
commit 781ff5b76b
19 changed files with 424 additions and 51 deletions
+47
View File
@@ -0,0 +1,47 @@
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <tuple>
struct S {
int n;
std::string s;
float d;
bool operator<(const S& rhs) const
{
// compares n to rhs.n,
// then s to rhs.s,
// then d to rhs.d
return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
}
};
int main()
{
std::set<S> mySet;
// pre C++17:
{
S value{42, "Test", 3.14};
std::set<S>::iterator iter;
bool inserted;
// unpacks the return val of insert into iter and inserted
std::tie(iter, inserted) = mySet.insert(value);
if (inserted)
std::cout << "Value was inserted\n";
}
// with C++17:
{
S value{100, "abc", 100.0};
const auto [iter, inserted] = mySet.insert(value);
if (inserted)
std::cout << "Value(" << iter->n << ", " << iter->s << ", ...) was inserted" << "\n";
}
}
+8
View File
@@ -0,0 +1,8 @@
#include <opencv2/core.hpp>
#include <iostream>
int main(int argc, char** argv)
{
std::cout << cv::getBuildInformation() << std::endl;
return 0;
}
+16 -1
View File
@@ -27,10 +27,25 @@ def fixtures_path(tests_path):
return os.path.join(tests_path, "fixtures")
@pytest.fixture(scope="session")
def scripts_path(fixtures_path: str):
return os.path.join(fixtures_path, "scripts")
@pytest.fixture(scope="session")
def compiler_cpp_17_fpath(fixtures_path: str):
return os.path.join(fixtures_path, "compiler", "cpp_17.cu")
@pytest.fixture(scope="session")
def compiler_opencv_fpath(fixtures_path: str):
return os.path.join(fixtures_path, "compiler", "opencv.cu")
@pytest.fixture(scope="session")
def sample_magic_cu_line():
# fmt: off
return '--profile --profiler-args "--metrics l1tex__t_sectors_pipe_lsu_mem_global_op_ld.sum"' # noqa: E501
return '--profile --profiler-args "--metrics l1tex__t_sectors_pipe_lsu_mem_global_op_ld.sum" --compiler-args "--optimize 3"' # noqa: E501
# fmt: on
Vendored Executable
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
# this is a mock of nsight compute cli tool that just executes the program
# given as the last argument
"${@: -1}"
echo "==WARNING== No kernels were profiled"
+115 -4
View File
@@ -3,10 +3,12 @@ import math
import os
import re
import shutil
import subprocess
from typing import List
import pytest
from nvcc4jupyter.parsers import get_parser_cuda, set_defaults
from nvcc4jupyter.plugin import NVCCPlugin
@@ -36,11 +38,19 @@ def copy_source_to_group(
return destination_fpath
@pytest.fixture(autouse=True, scope="session")
def before_all(scripts_path: str):
os.environ["PATH"] = scripts_path + os.pathsep + os.environ["PATH"]
@pytest.fixture(autouse=True, scope="function")
def before_each(plugin: NVCCPlugin):
shutil.rmtree(plugin.workdir, ignore_errors=True) # before test
# BEFORE TESTS
set_defaults(compiler_args="", profiler_args="")
shutil.rmtree(plugin.workdir, ignore_errors=True)
yield
pass # after test
# AFTER TESTS
pass
def test_save_source(plugin: NVCCPlugin, sample_cuda_code: str) -> None:
@@ -88,6 +98,62 @@ def test_compile(
plugin._compile(gname)
def test_compile_args(
plugin: NVCCPlugin,
compiler_cpp_17_fpath: str,
):
gname = "test_compile_args"
copy_source_to_group(compiler_cpp_17_fpath, gname, plugin.workdir)
exec_fpath = plugin._compile(gname, compiler_args="--std c++17")
assert os.path.exists(exec_fpath)
# should fail due to the source file having c++ 17 features
with pytest.raises(subprocess.CalledProcessError):
exec_fpath = plugin._compile(gname, compiler_args="--std c++14")
output = plugin._compile_and_run(
group_name=gname,
args=argparse.Namespace(
timeit=False,
profile=True,
profiler_args=lambda: "",
compiler_args=lambda: "--std c++14",
),
)
assert "errors detected in the compilation of" in output
def test_compile_opencv(
plugin: NVCCPlugin,
compiler_opencv_fpath: str,
):
gname = "test_compile_opencv"
copy_source_to_group(compiler_opencv_fpath, gname, plugin.workdir)
# check that "pkg-config" exists
assert subprocess.check_call(["which", "pkg-config"]) == 0
opencv_compile_options = (
subprocess.check_output(
args=["pkg-config", "--cflags", "--libs", "opencv4"]
)
.decode()
.strip()
)
output = plugin._compile_and_run(
group_name=gname,
args=argparse.Namespace(
timeit=False,
profile=True,
profiler_args=lambda: "",
compiler_args=lambda: opencv_compile_options,
),
)
assert "General configuration for OpenCV" in output
def test_run(
plugin: NVCCPlugin,
sample_cuda_fpath: str,
@@ -143,7 +209,13 @@ def test_compile_and_run_multiple_files(
for fpath in multiple_source_fpaths:
copy_source_to_group(fpath, gname, plugin.workdir)
output = plugin._compile_and_run(
gname, argparse.Namespace(timeit=False, profile=True, profiler_args="")
group_name=gname,
args=argparse.Namespace(
timeit=False,
profile=True,
profiler_args=lambda: "",
compiler_args=lambda: "",
),
)
check_profiler_output(output)
@@ -165,7 +237,13 @@ def test_compile_and_run_multiple_files_shared(
else:
copy_source_to_group(fpath, "shared", plugin.workdir)
output = plugin._compile_and_run(
gname, argparse.Namespace(timeit=False, profile=True, profiler_args="")
group_name=gname,
args=argparse.Namespace(
timeit=False,
profile=True,
profiler_args=lambda: "",
compiler_args=lambda: "",
),
)
check_profiler_output(output)
@@ -181,6 +259,29 @@ def test_read_args(plugin: NVCCPlugin):
assert math.isclose(args.b, 0.75)
def test_set_defaults():
parser = get_parser_cuda()
args = parser.parse_args([])
assert args.profiler_args() == ""
assert args.compiler_args() == ""
set_defaults(profiler_args="123")
args = parser.parse_args([])
assert args.profiler_args() == "123"
assert args.compiler_args() == ""
set_defaults(compiler_args="456")
args = parser.parse_args([])
assert args.profiler_args() == "123"
assert args.compiler_args() == "456"
set_defaults(profiler_args="")
args = parser.parse_args([])
assert args.profiler_args() == ""
assert args.compiler_args() == "456"
set_defaults(profiler_args="123")
args = parser.parse_args(["--profiler-args", "789"])
assert args.profiler_args() == "789"
assert args.compiler_args() == "456"
def test_magic_cuda(
capsys,
plugin: NVCCPlugin,
@@ -191,6 +292,16 @@ def test_magic_cuda(
check_profiler_output(capsys.readouterr().out)
def test_magic_cuda_bad_args(
capsys,
plugin: NVCCPlugin,
sample_cuda_code: str,
):
plugin.cuda("--this-is-an-unrecognized-argument", sample_cuda_code)
output = capsys.readouterr().out
assert output.startswith("usage: ")
def test_magic_cuda_group_save(plugin: NVCCPlugin, sample_cuda_code: str):
gname = "test_save_source"
sname = "sample.cu"