{"id":25371032,"url":"https://github.com/hpi-epic/gpucsl","last_synced_at":"2025-10-30T05:31:15.798Z","repository":{"id":41581531,"uuid":"472815669","full_name":"hpi-epic/gpucsl","owner":"hpi-epic","description":"Constraint-based Causal Structure Learning on GPUs.","archived":false,"fork":false,"pushed_at":"2022-11-23T18:32:42.000Z","size":143,"stargazers_count":38,"open_issues_count":9,"forks_count":1,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-01-13T09:56:47.447Z","etag":null,"topics":["csl","cuda","cupy","gpu-computing","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hpi-epic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-22T14:55:28.000Z","updated_at":"2024-03-18T08:50:26.000Z","dependencies_parsed_at":"2023-01-21T09:15:34.229Z","dependency_job_id":null,"html_url":"https://github.com/hpi-epic/gpucsl","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hpi-epic%2Fgpucsl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hpi-epic%2Fgpucsl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hpi-epic%2Fgpucsl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hpi-epic%2Fgpucsl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hpi-epic","download_url":"https://codeload.github.com/hpi-epic/gpucsl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238821447,"owners_count":19536223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csl","cuda","cupy","gpu-computing","python"],"created_at":"2025-02-15T02:21:11.972Z","updated_at":"2025-10-30T05:31:10.484Z","avatar_url":"https://github.com/hpi-epic.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Python tests + coverage](https://github.com/hpi-epic/gpucsl/actions/workflows/test-python.yml/badge.svg)\n![test benchmarks](https://github.com/hpi-epic/gpucsl/actions/workflows/test-benchmarks.yml/badge.svg)\n![test cuda](https://github.com/hpi-epic/gpucsl/actions/workflows/test-cuda.yml/badge.svg)\n![lint python](https://github.com/hpi-epic/gpucsl/actions/workflows/lint-python.yml/badge.svg)\n![lint cuda](https://github.com/hpi-epic/gpucsl/actions/workflows/lint-cuda.yml/badge.svg)\n\n# GPUCSL\n\n`GPUCSL` is a python library for constraint-based causal structure learning using Graphics Processing Units (GPUs). In particular, it utilizes CUDA for GPU acceleration to speed up the well-known PC algorithm.\n\n## Features\n\n- Performant GPU implementation of the PC algorithm (covers discrete, and multivariate normal distributed data), see [General Notes](#notes);\n- Multi-GPU support (experimental; for now, only for gaussian CI kernel);\n- Easy to install and use, see [Usage](#usage);\n- A Command Line Interface (CLI);\n- Modular, extensible, tested thoroughly.\n\n## \u003ca name=\"notes\"\u003e\u003c/a\u003e General Notes\n\n`GPUCSL` enables the GPU-accelerated estimation of the equivalence class of a data generating Directed Acyclic Graph (DAG) from observational data via constraint-based causal structure learning, cf. Kalisch et al. [^Kalisch] or Colombo and Maathuis [^Colombo]. Within the equivalence class, all DAGs have the same skeleton and the same v-structures and they can be uniquely represented by a Completely Partially Directed Acyclic Graph (CPDAG). In this context, `GPUCSL` implements the fully order-independent version of the PC algorithm, called PC-stable, to estimate the CPDAG under common faithfulness and sufficiency assumptions, see Colombo and Maathuis [^Colombo]. Hence, the implementation follows the `pc`-function within the R-package `pcalg` (For more information, see the [pcalg-Documentation](https://cran.r-project.org/web/packages/pcalg/pcalg.pdf#pc)). In particular, in the case of conflicts within the orientation phase, conflicts are solved similar to the `pc` within the `pcalg` implementation and yield matching results.\n\nNote, that `GPUCSL` provides kernel implementations that cover conditional independence (CI) tests for discrete distributed data according to the ideas of Hagedorn and Huegle[^HagedornDiscrete]. Implementation of the CI tests for multivariate normal (or Gaussian) distributed data follows the ideas of Schmidt et al. [^SchmidtGaussian] and Zarebavani et al. [^ZarebavaniCupc].\n\n## \u003ca name=\"usage\"\u003e\u003c/a\u003e  Usage\n\nLinux and a NVIDIA GPU with CUDA are required. We support running on multiple GPUs (experimental; for now, only for Gaussian CI kernel - `GaussianPC`).\n\n### CLI\n\nWith the CLI, the PC algorithm is executed on the specified datasets. Three output files will be written to the specified directory:\n\n- {dataset}.gml - the resulting CPDAG  containing the causal relationships\n- {dataset}_pmax.csv - the maximum pvalues used for the conditional independence tests\n- {dataset}_sepset.csv - the separation sets for the removed edges\n- {dataset}_config.txt - the parameters the CLI got called with\n\nAll paths you give to the CLI are relative to your current directory.\nAn example call for `GPUCSL` with a CI test for multivariate normal or Gaussian distributed data could look like this (assuming your data is in \"./data.csv\"):\n\n```bash\npython3 -m gpucsl --gaussian -d ./data.csv -o . -l 3\n```\n\n### Python API\n\n`GPUCSL` provides a python API for:\n\n- `GaussianPC` - implements the full PC algorithm for multivariate normal data. Outputs the CPDAG from observational data. Similar to the CLI.\n- `DiscretePC` -implements the full PC algorithm for discrete data. Outputs the CPDAG from observational data. Similar to the CLI.\n- `discover_skeleton_gpu_gaussian` - determines the undirected skeleton graph for gaussian distribution\n- `discover_skeleton_gpu_discrete` - determines the undirected skeleton graph for discrete distribution\n- `orient_edges` - orients the edges of the undirected skeleton graph by detection of v-structures and application of Meek's orientation rules. Outputs the CPDAG from skeleton.\n\nAdditional detail is found in the [API description](https://github.com/hpi-epic/gpucsl/blob/main/docs/Public-api.md).\n\nThe following code snippet provides a small example for using `GaussianPC`:\n```python\nimport numpy as np\nfrom gpucsl.pc.pc import GaussianPC\n\nsamples = np.random.rand(1000, 10)\nmax_level = 3\nalpha = 0.05\n((directed_graph, separation_sets, pmax, discover_skeleton_runtime,\n  edge_orientation_runtime, discover_skeleton_kernel_runtime),\n    pc_runtime) = GaussianPC(samples,\n                     max_level,\n                     alpha).set_distribution_specific_options().execute()\n\n```\n\nAdditional usage examples can be found in `docs/examples/`.\n\n### Multi GPU support\n\nMulti GPU support is currently only implemented for the gaussian CI kernel (`GaussianPC`) for skeleton discovery. The adjacency matrix (skeleton) is partitioned horizontally, and each GPU executes the CI tests on the assigned partition. For example, in the case of the dataset with 6 variables and 3 GPUs, the first GPU executes CI tests on edges 0-i, 1-i, where i is in {0..5\\} (0-indexing), the second GPU executes CI tests on edges 2-i, 3-i and so on.\n\nIn case of an edge being deleted on multiple GPUs in the same level (for example, the edge 1-3 is deleted on the first GPU, the edge 3-1 is deleted on the second GPU in the example above), the separation set with the highest p-value is written to the end result (along with the corresponding p-value).\n\n## Installation\n\n- Install cuda toolkit (see also \u003chttps://docs.cupy.dev/en/stable/install.html\u003e).\n- Optional, but recommended: activate a virtual python environment, e.g. `python3 -m venv venv \u0026\u0026 . venv/bin/activate`\n- Make sure to manually install the cupy version that matches your installed cuda version (\u003chttps://docs.cupy.dev/en/stable/install.html#installing-cupy-from-pypi\u003e). For example, if cuda 11.2 is installed, run `pip install cupy-cuda112`.\n- `pip install gpucsl`\n\n## How to use with docker\n\nFirst install Docker (for instructions refer to: \u003chttps://docs.docker.com/get-docker/\u003e)\nPlease remember: you will still need a NVIDIA GPU and the CUDA Toolkit installed to used the Docker image.\n\nThe current dockerfiles are written with CUDA version 11.2 as a target. Should your host system have a different version installed\n(you can look it up by running ```nvidia-smi -q -u``` and look for CUDA Version), you should go into the dockerfile and change the version\nin line 1 (the from statement) and in line 29 where the correct cupy version is installed.\n\nTo just use gpucsl:\n\n```\ndocker build --target gpucsl -t gpucsl .\ndocker run --runtime=nvidia --gpus all -i -t gpucsl\n```\n\nIf you want to upload/download files from/to the container run (to get the container id look it up by: ```docker container ps```):\n\n```\n# upload your-file.txt to container from the current directory into the directory where gpucsl is installed\ndocker cp your-file.txt container_id:/gpucsl/your-file.txt\n\n# download your-file.txt from container where gpucsl is installed to current directory\ndocker cp container_id:/gpucsl/your-file.txt your-file.txt\n```\n\nIf you want to run the benchmarks:\n\n```\ndocker build --target gpucsl-benchmarks -t benchmarks .\ndocker run --runtime=nvidia --gpus all -i -t benchmarks\n```\n\n## \u003ca name=\"CLIdocumentation\"\u003e\u003c/a\u003e Full CLI Documentation\n\nThe following options are available:\n| Shorthand  |  Longform |  Description |\n|---|---|---|\n| | --gaussian | Executes Fisher’s z-transformed (partial) correlation-based CI test for multvariate normal (or Gaussian) distributed data; Either this or discrete have to be set! |\n| | --discrete | Executes Pearson’s χ2 CI test for discrete distributed data; Either this or gaussian have to be set! |\n| -a | --alpha  | Sets the alpha level for PC algorithm to use. Default is 0.05. |\n| -b | --debug   | Is a flag for debugging the kernels. When activated kernels get compiled with debug flag and lineinfo enabled. |\n| -c | --correlation-matrix  | Defines the path to a cached correlation matrix file in csv format. You still have to give a dataset (-d/--dataset option)! |\n| -d | --dataset   |  (required) Defines the path to your input data in csv format; Is relative to your current directory |\n| -h | --help   |  shows a list and a sort explanation of all available options |\n| -g | --gpus  | Indices of GPUs that should be used for independence test calculation (currently only supported for gaussian independence test). When not specified will use all available GPUs. |\n| -l | --max-level  | Gives the max level for the PC algorithm (level of the pc algorithm is \u003c= max level) |\n| -o | --output-directory  |  (required) Defines the output directory; Is relative to your current directory |\n| -s | --sync-device  | Index of the GPU used to sync the others (currently only supported for gaussian independence test). Default is 0 |\n| -v | | Prints verbose output |\n| -vv | | Prints debug output |\n\n## Development\n\n### Dependencies setup\n\n- Clone the repo\n- From the project dir, call `./scripts/download-data.sh` (see `download-data.sh` section in [scripts](#scripts)) to download the data folder from dropbox. It contains several example/test datasets.\n- It is recommended to use a virtual environment: `python3 -m venv venv \u0026\u0026 source venv/bin/activate` (in bash, zsh).\n- Upgrade pip and install build: `python3 -m pip install --upgrade pip build`.\n- Make sure to install the cuda toolkit and cupy (see [installation](#installation)).\n- Run `pip install .` to install the release package.\n- Run `pip install -e \"./[dev]\"` to also install for development, with dev dependencies.\n\n### Linting Setup\n\n- Install clang-tidy and clang-format `sudo apt install clang-format`, `sudo apt install clang-tidy`.\n- Set up git to use our hooks `git config --local core.hooksPath .githooks/` to execute lint checks on pushing.\n- You can manually lint code with `./scripts/lint-python.sh` and `./scripts/lint-cuda.sh`.\n- You can autofix code with `./scripts/lint-python.sh --fix` and `./scripts/lint-cuda.sh --fix`.\n- Import `.vscode/settings.json` if you use vscode. This sets up VSCode to automatically run `black` and `clang-format` (respectively) on save.\n\n### Building a Package\n\n- Build sdist: `python3 -m build`.\n- Build for dev: `python3 -m pip install --editable .` (installs it locally).\n\n### Running Tests\n\n- Make sure to have your python environment activated and run `python3 -m pip install -e \"./[dev]\"`.\n- Run python tests: `pytest` (or in VSCode go to \"Testing\").\n- There are additional flags:\n  - for tests that take a long time and end-to-end tests from installation to CLI call, there is `pytest --run_slow`;\n  - for CI only tests, there is `pytest --run_testPyPI`.\n- Run cuda tests: `./scripts/test-cuda.sh`.\n\n### Release a new version using the github action\n\n- Bump the version in setup.cfg and commit your change to main.\n- On this commit, create a new tag (e.g., `git tag v0.0.1` and `git push origin v0.0.1`)\n- Go to \u003chttps://github.com/hpi-epic/gpucsl/releases\u003e and create a new release for this tag with the same name as the version.\n- A github action will run on release and first test this deployment on testPyPi and then publish the library to pypi.\n\n### Manually publish to PyPi\n\n ```bash\n python3 -m pip install --upgrade build twine\n python3 -m build\n # Upload to testPyPi\n # use __token__ as username and the pypi token as password\n python3 -m twine upload --repository testpypi dist/*\n # Upload to PyPi\n python3 -m twine upload dist/*\n ```\n\n## Scripts\n\nWe provide some helper scripts for data generation, testing, and benchmarking.\n\nTo run some of the scripts below, a working R installation is required.\n\n### R setup\n\nAn R installation with the following packages is needed. These steps were tested with\nR 4.1.2 on Ubuntu 20.04.3 LTS.\n\n- install R: see \u003chttps://cran.r-project.org/bin/linux/ubuntu/\u003e.\n\n- install further required packages\n\n```bash\napt install -y r-cran-fastica\napt install -y libv8-3.14-dev\napt install -y libcurl4-openssl-dev\napt install -y libgmp3-dev\n```\n\n- install R packages // TODO RScript to be tested\n\n```R\ninstall.packages(\"BiocManager\")\nBiocManager::install(version = \"3.14\")\nBiocManager::install(c(\"graph\", \"RBGL\", \"Rgraphviz\"))\ninstall.packages(\"pcalg\")\ninstall.packages(\"XML\")\ninstall.packages(\"tictoc\")\ninstall.packages(\"here\")\ninstall.packages(\"bnlearn\")\ninstall.packages(\"igraph\")\ninstall.packages(\"optparse\")\n```\n\n### `use_pcalg_gaussian.R`\n\nThis can be used to run the R-package `pcalg` on test data and output its results (as comparison for gpucsl). Some of the outputs are already contained in the `data` folder.\n\nUsage (make sure to do the call from the top-level project folder):\n\n- `./scripts/use_pcalg_gaussian.R {dataset}`;\n- for example: `./scripts/use_pcalg_gaussian.R NCI-60`.\n\nAssumes that \"NCI-60\" folder lies in the `data` folder, also works for all other datasets in `data`.\n\n### `download-data.sh`\n\nCall this script once to download all test data from a dropbox folder (without having to generate some parts of it yourself which can take a long time). It will create a `data` folder. Please check dataset license information in [dropbox](https://www.dropbox.com/sh/t5jw5vbwg8gaoxt/AAA-oQ9FMp2a_Ou7JuhOMiVca?dl=0) `README.md` before downloading.\n\n### `use_bnlearn_discrete.r`\n\nThis script can be used to generate discrete test data using the R-package bnlearn. The outputs necessary for the package tests can be generated by `./preprare-test-data.sh`, which internally calls this script.\nThe data needs to be in the data folder.\nUsage:\n\n- `Rscript use_bnlearn_discrete.r {dataset_name} {maximum_level}`;\n- for example: `Rscript use_bnlearn_discrete.r alarm 3`.\n\nMake sure to do the call from the scripts folder.\n\n### `encode-discrete-data.py`\n\nThis is a simple wrapper around sklearn's OrdinalEncoder to allow csv data that is not already encoded to be loaded into the library.\nUsage:\n\n- `python3 -m encode-discrete-data.py {dataset_name}`;\n- for example: `python3 -m encode-discrete-data.py alarm`.\n\n### Benchmarks\n\n- To execute, run `./benchmarks/run_benchmarks.sh`.\n  - The script will tell you the output folder where it wrote the benchmark run results. It automatically installs R dependencies. You can also specify which benchmarks to run in the first parameter.\n  - To run the benchmarks, you have to place the cupc repo in the benchmarks/cupc subdirectory. A forked version with timing annotations is available at \u003chttps://github.com/benrobby/cupc\u003e.\n- Once completed, open `benchmarks/visualization` notebooks (e.g. in VSCode just open the file, for instructions see \u003chttps://code.visualstudio.com/docs/datascience/jupyter-notebooks\u003e). In the notebook, specify the benchmark results folder (the one from step 1) and run all cells.\n\n## Contributors\n\n- Tom Braun (@BraunTom)\n- Christopher Hagedorn (@ChristopherSchmidt89)\n- Johannes Huegle (@JohannesHuegle)\n- Ben Hurdelhey (@benrobby)\n- Dominik Meier (@XPerianer)\n- Petr Tsayun (@PeterTsayun)\n\n## License\n\nThis project is licensed under the MIT license (see `LICENSE.txt`) unless otherwise noted in the respective source files:\n\n- `gpucsl/pc/helpers.py`;\n\nFor the license information of datasets, please check `README.md` in [dropbox](https://www.dropbox.com/sh/t5jw5vbwg8gaoxt/AAA-oQ9FMp2a_Ou7JuhOMiVca?dl=0) before downloading datasets.\n\n## References\n\n[^Kalisch]: Kalisch M., Mächler M., Colombo D., Maathuis M.H., Bühlmann P. (2012). \"Causal Inference Using Graphical Models with the R Package pcalg.\" Journal of Statistical Software, 47(11), pp. 1–26.\n[^Colombo]: Colombo D., and Maathuis, M.H. (2014). \"Order-independent constraint-based causal structure learning.\" Journal of Machine Learning Research 15 3921-3962.\n[^HagedornDiscrete]: Hagedorn, C., and Huegle, J. (2021). \"GPU-Accelerated Constraint-Based Causal Structure Learning for Discrete Data.\" Proceedings of the 2021 SIAM International Conference on Data Mining (SDM). pp. 37–45.\n[^SchmidtGaussian]: Schmidt, C., Huegle, J., and Uflacker, M. (2018). \"Order-independent constraint-based causal structure learning for gaussian distribution models using GPUs.\" Proceedings of the 30th International Conference on Scientific and Statistical Database Management (SSDBM). pp. 19:1–19:10.\n[^ZarebavaniCupc]: Zarebavani, B., Jafarinejad, F., Hashemi, M., \u0026 Salehkaleybar, S. (2020). cuPC: CUDA-Based Parallel PC Algorithm for Causal Structure Learning on GPU. IEEE Transactions on Parallel and Distributed Systems, 31(3), 530–542.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhpi-epic%2Fgpucsl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhpi-epic%2Fgpucsl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhpi-epic%2Fgpucsl/lists"}