diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c02d5c5..6050459 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,3 +23,13 @@ jobs: with: chapel_version: latest run_optional_tests: true + test-chpl-280: + uses: ./.github/workflows/chpl-tests.yml + with: + chapel_version: 2.8.0 + run_optional_tests: false + test-chpl-nightly: + uses: ./.github/workflows/chpl-tests.yml + with: + chapel_version: nightly + run_optional_tests: false diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 999c96a..605d3e2 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -11,8 +11,6 @@ jobs: # this just runs the benchmarks to make sure they compile and run test-benchmarks: - # TODO: setup-chpl doesn't work with nightly yet - if: ${{ inputs.chapel_version != 'nightly' }} strategy: fail-fast: true matrix: @@ -22,35 +20,32 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Install Chapel - uses: jabraham17/setup-chpl@v1 - with: - version: ${{ inputs.chapel_version }} - backend: ${{ matrix.backend }} - name: Install Python Dependencies run: | python3 -m venv .venv ./.venv/bin/python3 -m pip install --upgrade pip ./.venv/bin/python3 -m pip install pydantic + - name: Setup chapel + uses: jabraham17/setup-chpl@v1 + with: + version: ${{ inputs.chapel_version }} + backend: ${{ matrix.backend }} - name: Setup fortran - # fortran-lang/setup-fortran has some bugs when running in a container - # and bad usage of sudo, so use jabraham17/setup-fortran@fix-cd until - # those are fixed - uses: jabraham17/setup-fortran@fix-cd + uses: fortran-lang/setup-fortran@v1 with: compiler: gcc - version: latest + version: 15 - name: Setup Rust uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable - - name: Build CVL Dependencies - run: | - ./third-party/sleef/install.sh - name: Run Benchmarks run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + source util/localRegistry.sh + ./.venv/bin/python3 ./util/bench.py \ --schema benchmarks/benchmarks.json \ - --trials 3 --small \ - --cvl-options "$(./compile.py --sleef)" + --trials 3 --small diff --git a/.github/workflows/bump-minor-version.yml b/.github/workflows/bump-minor-version.yml new file mode 100644 index 0000000..b5eb876 --- /dev/null +++ b/.github/workflows/bump-minor-version.yml @@ -0,0 +1,71 @@ +name: Bump minor version + +on: + workflow_dispatch: + workflow_run: + workflows: [Publish to mason registry] + types: [completed] + +jobs: + bump-minor: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }} + steps: + - uses: actions/checkout@v4 + - name: Exit if branch exists + run: | + BRANCH_NAME="update-version" + if git ls-remote --heads origin $BRANCH_NAME | grep -q $BRANCH_NAME; then + echo "Branch $BRANCH_NAME already exists." + exit 1 + fi + - name: Create a new branch + run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git checkout -b update-version + git push --set-upstream origin update-version + - name: Get version from Mason.toml + id: previous_version + uses: mikefarah/yq@v4 + with: + cmd: yq .brick.version Mason.toml + - name: Bump Minor Version + id: bump_version + run: | + PREVIOUS_VERSION=${{ steps.previous_version.outputs.result }} + MAJOR=$(echo $PREVIOUS_VERSION | cut -d. -f1) + MINOR=$(echo $PREVIOUS_VERSION | cut -d. -f2) + NEW_MINOR=$((MINOR + 1)) + NEW_VERSION="$MAJOR.$NEW_MINOR.0" + echo "New version: $NEW_VERSION" + echo "result=$NEW_VERSION" >> $GITHUB_OUTPUT + - name: Update version in Mason.toml + uses: mikefarah/yq@v4 + with: + cmd: yq -i '.brick.version="${{ steps.bump_version.outputs.result }}"' Mason.toml + - name: Get name from Mason.toml + id: package_name + uses: mikefarah/yq@v4 + with: + cmd: yq .brick.name Mason.toml + - name: Update version in README.md + run: | + NAME=${{ steps.package_name.outputs.result }} + NEW_VERSION=${{ steps.bump_version.outputs.result }} + sed "s/mason add $NAME@[0-9]*\.[0-9]*\.[0-9]*/mason add $NAME@$NEW_VERSION/g" README.md > README.tmp && mv README.tmp README.md + - name: Commit and push changes + run: | + git add Mason.toml + git add README.md + git commit -m "Bump version to ${{ steps.bump_version.outputs.result }}" + git push origin update-version + - name: create pull request + run: > + gh pr create + -B main + -H update-version + --title 'Bump version for next release' + --body 'Bump the version in prep for next release' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/chpl-tests.yml b/.github/workflows/chpl-tests.yml index 4e0d88a..ee35d95 100644 --- a/.github/workflows/chpl-tests.yml +++ b/.github/workflows/chpl-tests.yml @@ -13,42 +13,44 @@ on: default: true jobs: - # brew only supports nightly and latest + # brew only supports latest # brew doesn't support linux arm - # TODO: brew will soon support ML chapel, so we can add comm!=none jobs for brew then mason-test-brew: - if: ${{ inputs.chapel_version == 'nightly' || inputs.chapel_version == 'latest' }} + if: ${{ inputs.chapel_version == 'latest' }} strategy: fail-fast: false matrix: backend: [llvm, gnu, clang] os: [ubuntu-latest, macos-latest] + comm: [none, gasnet] exclude: - os: ubuntu-latest backend: clang - os: macos-latest backend: gnu + - os: ubuntu-latest + comm: gasnet + - comm: gasnet + backend: clang runs-on: ${{ matrix.os }} env: CHPL_TARGET_COMPILER: ${{ matrix.backend }} + CHPL_COMM: ${{ matrix.comm }} + GASNET_SPAWNFN: L + GASNET_ROUTE_OUTPUT: 0 + GASNET_QUIET: Y + GASNET_MASTERIP: 127.0.0.1 + GASNET_WORKERIP: 127.0.0.0 + CHPL_RT_OVERSUBSCRIBED: yes steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Homebrew uses: Homebrew/actions/setup-homebrew@main - name: Install Chapel - run: | - if [ "${{ inputs.chapel_version }}" = "nightly" ]; then - brew install --HEAD chapel - else - brew install chapel - fi - - name: Build CVL Dependencies - run: | - ./third-party/sleef/install.sh + run: brew install chapel - name: Run Tests - run: | - ./util/test.sh + run: mason test --parallel --show mason-test-docker: strategy: @@ -57,7 +59,6 @@ jobs: image: - chapel/chapel:${{ inputs.chapel_version }} - chapel/chapel-gasnet:${{ inputs.chapel_version }} - - chapel/chapel-gasnet-smp:${{ inputs.chapel_version }} backend: [llvm, gnu] os: [ubuntu-latest, ubuntu-24.04-arm] runs-on: ${{ matrix.os }} @@ -68,29 +69,21 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up CMake - # cmake testing doesn't work on arm yet - if: ${{ matrix.os != 'ubuntu-24.04-arm' }} - uses: jwlawson/actions-setup-cmake@v2.0.2 - - name: Build CVL Dependencies - run: | - ./third-party/sleef/install.sh - name: Run Tests - # FIXME: smp testing on linux 64 breaks with multi locale code? But only - # in the CI, local testing seems fine, - if: ${{ ! (matrix.image == format('chapel/chapel-gasnet-smp:{0}', inputs.chapel_version) && matrix.os == 'ubuntu-latest') }} - run: | - ./util/test.sh - - name: Run CMake Tests - # cmake testing doesn't work on arm yet - if: ${{ matrix.os != 'ubuntu-24.04-arm' }} - run: | - ./util/testCMake.sh - - name: Run examples + run: mason test --parallel --show + - name: Check the examples build and run run: | - ./util/examples.sh + mason build --example + for example in $(ls example/*.chpl); do + example_name=$(basename $example) + if [ "$example_name" = "StreamConfig.chpl" ]; then + continue + fi + mason run --example $example_name + done test-benchmarks: + if: ${{ inputs.chapel_version == 'latest' }} uses: ./.github/workflows/bench.yml with: chapel_version: ${{ inputs.chapel_version }} @@ -103,8 +96,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Run lints - run: | - ./util/lint.sh + run: ./util/lint.sh python-tests: if: ${{ inputs.run_optional_tests }} @@ -112,7 +104,7 @@ jobs: strategy: fail-fast: true matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - name: Checkout uses: actions/checkout@v4 @@ -125,5 +117,4 @@ jobs: python3 -m pip install --upgrade pip python3 -m pip install tox - name: Run Python Tests - run: | - ./util/tox.sh + run: ./util/tox.sh diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6a2885a..938cec0 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -32,14 +32,14 @@ jobs: uses: actions/configure-pages@v5 - name: Build docs run: | - ./doc/build_docs.sh + mason doc - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: ./build/doc/html + path: ./doc/ deploy: - if: github.event_name == 'push' && github.repository == 'jabraham17/CVL' + if: github.event_name == 'push' && !github.event.repository.fork environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml deleted file mode 100644 index 1835e70..0000000 --- a/.github/workflows/nightly.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: nightly -# -# Runs the same tests as the CI, but using the latest Chapel nightly build. -# This prevents potential regressions from the latest changes in Chapel. This -# workflow runs on a weekly schedule and can also be triggered manually. -# -# This workflow also tests a couple of specific older Chapel versions to -# ensure compatibility. -# - -on: - schedule: - - cron: '0 0 * * 0' # Runs at 00:00 UTC every Sunday - workflow_dispatch: - -jobs: - test-chpl-nightly: - uses: ./.github/workflows/chpl-tests.yml - with: - chapel_version: nightly - run_optional_tests: false - test-chpl-2_6_0: - uses: ./.github/workflows/chpl-tests.yml - with: - chapel_version: 2.6.0 - run_optional_tests: false - test-chpl-2_5_0: - uses: ./.github/workflows/chpl-tests.yml - with: - chapel_version: 2.5.0 - run_optional_tests: false diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..e939226 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,76 @@ +name: Publish to mason registry + +on: + workflow_dispatch: + +jobs: + create-tag: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Get version from Mason.toml + id: version + uses: mikefarah/yq@v4 + with: + cmd: yq .brick.version Mason.toml + - name: Bump version and push tag + id: create_tag + uses: mathieudutour/github-tag-action@v6.2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + custom_tag: ${{ steps.version.outputs.result }} + tag_prefix: "v" + create_annotated_tag: true + push-to-mason-registry: + needs: create-tag + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + path: source-repo + - name: Get version from Mason.toml + id: version + uses: mikefarah/yq@v4 + with: + cmd: yq .brick.version source-repo/Mason.toml + - name: Get package name + id: package_name + uses: mikefarah/yq@v4 + with: + cmd: yq .brick.name source-repo/Mason.toml + - name: Checkout mason-registry fork + uses: actions/checkout@v4 + with: + repository: jabraham17/mason-registry + token: ${{ secrets.MASON_REGISTRY_PAT }} + path: mason-registry + - name: Create branch and add package + run: | + VERSION="${{ steps.version.outputs.result }}" + PACKAGE_NAME="${{ steps.package_name.outputs.result }}" + cd mason-registry + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git checkout -b "${PACKAGE_NAME}-${VERSION}" + mkdir -p "Bricks/${PACKAGE_NAME}" + cp ../source-repo/Mason.toml "Bricks/${PACKAGE_NAME}/${VERSION}.toml" + git add . + git commit -m "Add ${PACKAGE_NAME} ${VERSION}" + - name: Push changes + uses: ad-m/github-push-action@v1 + with: + github_token: ${{ secrets.MASON_REGISTRY_PAT }} + repository: jabraham17/mason-registry + branch: "${{ steps.package_name.outputs.result }}-${{ steps.version.outputs.result }}" + directory: mason-registry + - name: Create pull request + run: > + gh pr create + --repo chapel-lang/mason-registry + --head "jabraham17:${{ steps.package_name.outputs.result }}-${{ steps.version.outputs.result }}" + --base master + --title "Add ${{ steps.package_name.outputs.result }} ${{ steps.version.outputs.result }}" + --body "Add ${{ steps.package_name.outputs.result }} version ${{ steps.version.outputs.result }} to the mason registry" + env: + GH_TOKEN: ${{ secrets.MASON_REGISTRY_PRS }} + diff --git a/.gitignore b/.gitignore index 3e1e8c9..a8e9279 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ target/ Mason.lock build/ +doc/ .vscode/* !.vscode/extensions.json a.out @@ -10,3 +11,4 @@ __pycache__/ test.log .tox .MAX_LOCALES +.registry diff --git a/Mason.toml b/Mason.toml index 08a1f5d..69213dd 100644 --- a/Mason.toml +++ b/Mason.toml @@ -1,15 +1,15 @@ [brick] name="CVL" version="0.1.0" -author="Jade Abraham" -chplVersion="2.4.0" -license="Apache-2.0" -# TODO: commas inside of strings are broken in Mason -#copyright="2025, Jade Abraham" -copyright="2025; Jade Abraham" +chplVersion="2.8.0" type="library" +source="git@github.com:jabraham17/CVL.git" +authors=["Jade Abraham"] +copyrightYear="2025" +license="Apache-2.0" + compopts="--using-attribute-toolname=lint --no-overload-sets-checks --ccflags=-Wno-strict-prototypes" -docopts="--using-attribute-toolname=lint" +docopts="--using-attribute-toolname=lint --index=docs/index.rst" tests = [ "ArrTest.chpl", @@ -35,18 +35,11 @@ tests = [ "sleef/Trig.chpl", ] -# TODO: mason libraries don't let you `mason run` examples! [examples] examples = [ "stream.chpl", "streamExplicitVector.chpl", "streamVectorIterators.chpl" ] [dependencies] -[architecture] -[architecture.x86_64] -compopts = "--ccflags=-msse4.1 --ccflags=-mavx2 --ccflags=-mfma" -[architecture.arm64] -compopts = "--ccflags=-march=armv8.2-a+fp16" - [tool.chpl-language-server] module-dir = ["src"] diff --git a/README.md b/README.md index b4a3c62..8978889 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,22 @@ Portable SIMD intrinsics for the Chapel language. +## Installation + +Add CVL as a Mason dependency: + +```bash +mason add CVL@0.1.0 +``` + +## Usage + +See the examples directory for usage examples. + +## License + +See [Mason.toml](Mason.toml). + ## ChapelCon 2025 This library was presented at [ChapelCon 2025](https://chapel-lang.org/chapelcon25/#vectorlib). See the [slides](https://chapel-lang.org/ChapelCon/2025/chapel-vector-library.pdf) and [video recording](https://youtu.be/9zyjphsI2nA). diff --git a/benchmarks/benchmarks.json b/benchmarks/benchmarks.json index b408fec..57a6a2b 100644 --- a/benchmarks/benchmarks.json +++ b/benchmarks/benchmarks.json @@ -14,17 +14,15 @@ }, { "name": "vectorized", - "files": ["nbody/nbody.chpl"], - "language": "chpl", - "compopts": ["--fast", "CVL_OPTIONS"], + "directory": "nbody/nbodyVec", + "language": "mason", "execopts": ["--n=50000000"], "measure": ["RUNTIME"] }, { "name": "vectorized-fma", - "files": ["nbody/nbody-fma.chpl"], - "language": "chpl", - "compopts": ["--fast", "CVL_OPTIONS"], + "directory": "nbody/nbodyFma", + "language": "mason", "execopts": ["--n=50000000"], "measure": ["RUNTIME"] }, @@ -101,9 +99,8 @@ }, { "name": "vectorized", - "files": ["mandelbrot/mandelbrot-vec.chpl"], - "language": "chpl", - "compopts": ["--fast", "CVL_OPTIONS"], + "directory": "mandelbrot/mandelbrotVec", + "language": "mason", "execopts": ["--n=16000"], "measure": ["RUNTIME"] } @@ -139,9 +136,8 @@ }, { "name": "AoA-vectorized", - "files": ["flux/flux3.chpl"], - "language": "chpl", - "compopts": ["--fast", "CVL_OPTIONS"], + "directory": "flux/fluxVec", + "language": "mason", "execopts": ["--n=1000", "--m=1000", "--iterations=50", "--timing"], "measure": ["Time taken: ([0-9.]+)"] } @@ -162,9 +158,8 @@ }, { "name": "vectorized", - "files": ["kmeans/kmeans-vector.chpl"], - "language": "chpl", - "compopts": ["--fast", "--no-ieee-float", "CVL_OPTIONS"], + "directory": "kmeans/kmeansVec", + "language": "mason", "execopts": ["--n=100_000"], "execopts-small": ["--n=1000"], "measure": ["KMeans took ([0-9.]+)"] @@ -177,13 +172,10 @@ "versions": [ { "name": "baseline", - "files": ["trig/trigBench.chpl"], - "language": "chpl", + "directory": "trig", + "language": "mason", "compopts": [ - "--fast", - "--no-ieee-float", - "-svectorize=false", - "CVL_OPTIONS" + "-svectorize=false" ], "execopts": ["--n=10_000_000", "--timing"], "execopts-small": ["--n=10_000", "--timing"], @@ -191,13 +183,10 @@ }, { "name": "vectorized", - "files": ["trig/trigBench.chpl"], - "language": "chpl", + "directory": "trig", + "language": "mason", "compopts": [ - "--fast", - "--no-ieee-float", - "-svectorize=true", - "CVL_OPTIONS" + "-svectorize=true" ], "execopts": ["--n=10_000_000", "--timing"], "execopts-small": ["--n=10_000", "--timing"], @@ -211,36 +200,32 @@ "versions": [ { "name": "ScalarFloat", - "files": ["grayscale/grayscale.chpl"], - "language": "chpl", - "compopts": ["--fast", "--edition=preview", "--no-ieee-float", "CVL_OPTIONS"], + "directory": "grayscale", + "language": "mason", "execopts": ["--benchmark=Benchmark.ScalarFloat", "--n=30_000"], "execopts-small": ["--benchmark=Benchmark.ScalarFloat", "--n=500"], "measure": ["Time taken: ([0-9.]+)"] }, { "name": "VectorFloat", - "files": ["grayscale/grayscale.chpl"], - "language": "chpl", - "compopts": ["--fast", "--edition=preview", "--no-ieee-float", "CVL_OPTIONS"], + "directory": "grayscale", + "language": "mason", "execopts": ["--benchmark=Benchmark.VectorFloat", "--n=30_000"], "execopts-small": ["--benchmark=Benchmark.VectorFloat", "--n=500"], "measure": ["Time taken: ([0-9.]+)"] }, { "name": "ScalarInt", - "files": ["grayscale/grayscale.chpl"], - "language": "chpl", - "compopts": ["--fast", "--edition=preview", "--no-ieee-float", "CVL_OPTIONS"], + "directory": "grayscale", + "language": "mason", "execopts": ["--benchmark=Benchmark.ScalarInt", "--n=30_000"], "execopts-small": ["--benchmark=Benchmark.ScalarInt", "--n=500"], "measure": ["Time taken: ([0-9.]+)"] }, { "name": "VectorInt", - "files": ["grayscale/grayscale.chpl"], - "language": "chpl", - "compopts": ["--fast", "--edition=preview", "--no-ieee-float", "CVL_OPTIONS"], + "directory": "grayscale", + "language": "mason", "execopts": ["--benchmark=Benchmark.VectorInt", "--n=30_000"], "execopts-small": ["--benchmark=Benchmark.VectorInt", "--n=500"], "measure": ["Time taken: ([0-9.]+)"] diff --git a/benchmarks/flux/fluxVec/Mason.toml b/benchmarks/flux/fluxVec/Mason.toml new file mode 100644 index 0000000..c36531e --- /dev/null +++ b/benchmarks/flux/fluxVec/Mason.toml @@ -0,0 +1,9 @@ +[brick] +name = "fluxVec" +version = "0.1.0" +chplVersion = "2.7.0" +license = "None" +type = "application" + +[dependencies] +CVL = "0.0.0" diff --git a/benchmarks/flux/flux3.chpl b/benchmarks/flux/fluxVec/src/fluxVec.chpl similarity index 100% rename from benchmarks/flux/flux3.chpl rename to benchmarks/flux/fluxVec/src/fluxVec.chpl diff --git a/benchmarks/grayscale/.gitignore b/benchmarks/grayscale/.gitignore deleted file mode 100644 index 593cb73..0000000 --- a/benchmarks/grayscale/.gitignore +++ /dev/null @@ -1 +0,0 @@ -output.png diff --git a/benchmarks/grayscale/Mason.toml b/benchmarks/grayscale/Mason.toml new file mode 100644 index 0000000..2c97bcc --- /dev/null +++ b/benchmarks/grayscale/Mason.toml @@ -0,0 +1,10 @@ +[brick] +name="grayscale" +version="0.1.0" +chplVersion="2.7.0" +license="None" +type="application" +compopts="--edition=preview --no-ieee-float" + +[dependencies] +CVL = "0.0.0" diff --git a/benchmarks/grayscale/grayscale.chpl b/benchmarks/grayscale/src/grayscale.chpl similarity index 100% rename from benchmarks/grayscale/grayscale.chpl rename to benchmarks/grayscale/src/grayscale.chpl diff --git a/benchmarks/kmeans/kmeansVec/Mason.toml b/benchmarks/kmeans/kmeansVec/Mason.toml new file mode 100644 index 0000000..1c66b04 --- /dev/null +++ b/benchmarks/kmeans/kmeansVec/Mason.toml @@ -0,0 +1,10 @@ +[brick] +name = "kmeansVec" +version = "0.1.0" +chplVersion = "2.7.0" +license = "None" +type = "application" +compopts = "--no-ieee-float" + +[dependencies] +CVL = "0.0.0" diff --git a/benchmarks/kmeans/kmeans-vector.chpl b/benchmarks/kmeans/kmeansVec/src/kmeansVec.chpl similarity index 100% rename from benchmarks/kmeans/kmeans-vector.chpl rename to benchmarks/kmeans/kmeansVec/src/kmeansVec.chpl diff --git a/benchmarks/mandelbrot/mandelbrotVec/Mason.toml b/benchmarks/mandelbrot/mandelbrotVec/Mason.toml new file mode 100644 index 0000000..4b32184 --- /dev/null +++ b/benchmarks/mandelbrot/mandelbrotVec/Mason.toml @@ -0,0 +1,9 @@ +[brick] +name = "mandelbrotVec" +version = "0.1.0" +chplVersion = "2.7.0" +license = "None" +type = "application" + +[dependencies] +CVL = "0.0.0" diff --git a/benchmarks/mandelbrot/mandelbrot-vec.chpl b/benchmarks/mandelbrot/mandelbrotVec/src/mandelbrotVec.chpl similarity index 100% rename from benchmarks/mandelbrot/mandelbrot-vec.chpl rename to benchmarks/mandelbrot/mandelbrotVec/src/mandelbrotVec.chpl diff --git a/benchmarks/nbody/nbodyFma/Mason.toml b/benchmarks/nbody/nbodyFma/Mason.toml new file mode 100644 index 0000000..8c072de --- /dev/null +++ b/benchmarks/nbody/nbodyFma/Mason.toml @@ -0,0 +1,9 @@ +[brick] +name = "nbodyFma" +version = "0.1.0" +chplVersion = "2.7.0" +license = "None" +type = "application" + +[dependencies] +CVL = "0.0.0" diff --git a/benchmarks/nbody/nbody-fma.chpl b/benchmarks/nbody/nbodyFma/src/nbodyFma.chpl similarity index 100% rename from benchmarks/nbody/nbody-fma.chpl rename to benchmarks/nbody/nbodyFma/src/nbodyFma.chpl diff --git a/benchmarks/nbody/nbodyVec/Mason.toml b/benchmarks/nbody/nbodyVec/Mason.toml new file mode 100644 index 0000000..80daeed --- /dev/null +++ b/benchmarks/nbody/nbodyVec/Mason.toml @@ -0,0 +1,9 @@ +[brick] +name = "nbodyVec" +version = "0.1.0" +chplVersion = "2.7.0" +license = "None" +type = "application" + +[dependencies] +CVL = "0.0.0" diff --git a/benchmarks/nbody/nbody.chpl b/benchmarks/nbody/nbodyVec/src/nbodyVec.chpl similarity index 100% rename from benchmarks/nbody/nbody.chpl rename to benchmarks/nbody/nbodyVec/src/nbodyVec.chpl diff --git a/benchmarks/trig/Mason.toml b/benchmarks/trig/Mason.toml new file mode 100644 index 0000000..7416406 --- /dev/null +++ b/benchmarks/trig/Mason.toml @@ -0,0 +1,13 @@ + +[brick] +chplVersion = "2.7.0" +license = "None" +name = "trig" +type = "application" +version = "0.1.0" +compopts = "--no-ieee-float" + +[dependencies] +CVL = "0.0.0" + + diff --git a/benchmarks/trig/trigBench.chpl b/benchmarks/trig/src/trig.chpl similarity index 100% rename from benchmarks/trig/trigBench.chpl rename to benchmarks/trig/src/trig.chpl diff --git a/cmake/CVLConfig.cmake b/cmake/CVLConfig.cmake deleted file mode 100644 index 2b3e795..0000000 --- a/cmake/CVLConfig.cmake +++ /dev/null @@ -1,23 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -find_package(chpl REQUIRED) -project(cvl LANGUAGES CHPL) - -set(CVL_ROOT "${CMAKE_CURRENT_LIST_DIR}/..") -set(CVL_COMPILE_PY "${CVL_ROOT}/compile.py") - -message(STATUS "CVL: Determining compile options...") -message(STATUS "CVL: Using ${CVL_COMPILE_PY} to generate compile options") -execute_process( - COMMAND "${CVL_COMPILE_PY}" - OUTPUT_VARIABLE CVL_COMPOPTS_STR - RESULT_VARIABLE CVL_COMPOPTS_CODE - OUTPUT_STRIP_TRAILING_WHITESPACE -) -if(NOT CVL_COMPOPTS_CODE EQUAL 0) - message(FATAL_ERROR "CVL: Failed to determine proper compile options: ${CVL_COMPOPTS_CODE}") -endif() -message(STATUS "CVL: Compile options: ${CVL_COMPOPTS_STR}") -separate_arguments(CVL_COMPOPTS UNIX_COMMAND "${CVL_COMPOPTS_STR}") - -add_library(cvl INTERFACE) -target_link_options(cvl INTERFACE ${CVL_COMPOPTS}) diff --git a/compile.py b/compile.py deleted file mode 100755 index f64df6a..0000000 --- a/compile.py +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/env python3 - -# -# Get the command line flags to use this library in your code -# - -import sys -import os -import argparse as ap -from pathlib import Path - -# use pip vendor TOML if no system TOML is available (Python 3.10 or less) -try: - import tomllib -except ModuleNotFoundError: - import pip._vendor.tomli as tomllib - - -def get_arch(): - machine = os.uname()[4] - if machine == "aarch64": - return "arm64" - return machine - - -def get_os(): - platform = os.uname()[0] - return platform.lower() - - -class Project: - def __init__(self, workspace): - self.workspace = workspace - self.Mason_toml = workspace / "Mason.toml" - self.data = {} - self.sleef = False - self.load() - - def load(self): - with open(self.Mason_toml, "rb") as f: - self.data = tomllib.load(f) - - def get_arch_compopts(self): - arch = get_arch() - arch_specific = self.data.get("architecture", {}).get(arch, None) - arch_compopts = "" - if arch_specific is None: - sys.stderr.write("Unsupported architecture: {}\n".format(arch)) - else: - arch_compopts = arch_specific.get("compopts", "") - - if self.sleef: - sleef_dir = ( - self.workspace / "third-party" / "sleef" / "sleef-install" - ) - if sleef_dir.exists(): - arch_compopts += ( - " --set useSLEEF --set SLEEF_INSTALL='{}'".format(sleef_dir) - ) - if get_os() == "linux": - # FIXME: sleef static libs are not PIE, so disable for now - arch_compopts += ( - " --ccflags=-Wno-unused-command-line-argument" - + " --ccflags=-no-pie --ldflags=-no-pie" - ) - else: - install_script = ( - self.workspace / "third-party" / "sleef" / "install.sh" - ) - sys.stderr.write( - "Sleef directory not found: {}, try running {}`\n".format( - sleef_dir, install_script - ) - ) - exit(1) - - return arch_compopts - - def get_mason_compopts(self): - compopts = self.data["brick"].get("compopts", "") - return compopts - - def get_module_compopts(self): - src = self.workspace / "src" - module_compopts = "-M{}".format(src) - return module_compopts - - def get_compopts(self): - module_compopts = self.get_module_compopts() - mason_compopts = self.get_mason_compopts() - arch_compopts = self.get_arch_compopts() - return "{} {} {}".format(module_compopts, mason_compopts, arch_compopts) - - def get_docopts(self): - docopts = self.data["brick"].get("docopts", "") - return docopts - - def get_tests(self): - tests = self.data["brick"].get("tests", "") - return tests - - def get_examples(self): - examples = self.data["examples"].get("examples", []) - return "\n".join(examples) - - def generate_ops(self): - sys.path.insert(0, str(self.workspace / "util")) - from generate_ops import Parser, BinaryOpsGenerator - - expressions = Parser(self.workspace / "src" / "Vector.chpl").parse() - generator = BinaryOpsGenerator(expressions) - generator.generate(self.workspace / "src" / "Vector" / "Operators.chpl") - - -def main(): - - cvl_directory = Path(__file__).resolve().parent - project = Project(cvl_directory) - - a = ap.ArgumentParser() - a.add_argument( - "--module-compopts", - const=project.get_module_compopts, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--base-compopts", - const=project.get_mason_compopts, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--arch-compopts", - const=project.get_arch_compopts, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--all-compopts", - const=project.get_compopts, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--docopts", - const=project.get_docopts, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--list-tests", - const=project.get_tests, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--generate-ops", - const=project.generate_ops, - dest="action", - action="store_const", - default=project.get_compopts, - ) - a.add_argument( - "--sleef", - default=False, - action="store_true", - help="Use the Sleef library for vector math operations", - ) - a.add_argument( - "--examples", - const=project.get_examples, - dest="action", - action="store_const", - default=project.get_compopts, - ) - args = a.parse_args() - project.sleef = args.sleef - - res = args.action() - if res: - print(res) - - -if __name__ == "__main__": - main() diff --git a/doc/build_docs.sh b/doc/build_docs.sh deleted file mode 100755 index dbd84e5..0000000 --- a/doc/build_docs.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - -PROJECT_DIR=$(cd $(dirname $0); cd ..; pwd) - -(cd $PROJECT_DIR && set -x && rm -rf build && mkdir build) - -# generate the documentation source files -(cd $PROJECT_DIR && set -x && \ - chpldoc src/CVL.chpl --process-used-modules \ - $(./compile.py --docopts) \ - --save-sphinx build/doc --print-commands --no-html -o dummy \ -) - -# delete everything in build/doc/source except for the modules -(cd $PROJECT_DIR && set -x && \ - find build/doc/source -mindepth 1 -maxdepth 1 ! -name 'modules' -exec rm -rf {} + \ -) -# move the modules/src directory to the correct location -(cd $PROJECT_DIR && set -x && \ - mv build/doc/source/modules/src/* build/doc/source/ && \ - rmdir build/doc/source/modules/src && \ - rmdir build/doc/source/modules \ -) - -# copy in the correct index file -(cd $PROJECT_DIR && set -x && \ - cp doc/index.rst build/doc/source/index.rst \ -) - -# build the documentation -(cd $PROJECT_DIR && set -x && \ - python3 $(chpl --print-chpl-home)/third-party/chpl-venv/install/chpldeps \ - sphinx-build -W -n -c doc -b html \ - -d build/doc/build/doctrees build/doc/source build/doc/html \ -) diff --git a/doc/conf.py b/doc/conf.py deleted file mode 100644 index d676695..0000000 --- a/doc/conf.py +++ /dev/null @@ -1,61 +0,0 @@ -import os - -# use pip vendor TOML if no system TOML is available (Python 3.10 or less) -try: - import tomllib -except ModuleNotFoundError: - import pip._vendor.tomli as tomllib - -on_rtd = os.environ.get("READTHEDOCS", None) == "True" - -needs_sphinx = "1.0" - -extensions = [ - "sphinx.ext.todo", - "sphinxcontrib.chapeldomain", - "sphinx.ext.mathjax", -] - -source_suffix = ".rst" -root_doc = "index" - - -def get_metadata(): - with open( - os.path.join(os.path.dirname(__file__), "..", "Mason.toml"), "rb" - ) as f: - brick = tomllib.load(f)["brick"] - metadata = { - "name": brick["name"], - "version": brick["version"], - "author": brick.get("author", ""), - "license": brick.get("license", ""), - "copyright": brick.get("copyright", ""), - } - return metadata - - -metadata = get_metadata() - -project = metadata["name"] -author_text = metadata["author"] -copyright = metadata["copyright"] - -# The short X.Y version. -version = metadata["version"].split("-")[0] -# The full version, including alpha/beta/rc tags. -release = metadata["version"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -if not on_rtd: - html_theme = "sphinx_rtd_theme" - - html_theme_options = { - "sticky_navigation": True, - } diff --git a/doc/index.rst b/docs/index.rst similarity index 80% rename from doc/index.rst rename to docs/index.rst index 961c786..f786f8b 100644 --- a/doc/index.rst +++ b/docs/index.rst @@ -7,9 +7,9 @@ Core Library .. toctree:: :maxdepth: 1 - CVL - Vector - VectorRef + modules/src/CVL + modules/src/Vector + modules/src/VectorRef Intrinsics ********** @@ -19,7 +19,7 @@ CVL implements all of the higher level vector operations using a lower level lib .. toctree:: :maxdepth: 1 - Intrin + modules/src/Intrin Internal Intrinsics ~~~~~~~~~~~~~~~~~~~ @@ -29,10 +29,10 @@ These modules are the internal implementation types used by the intrinsics. They .. toctree:: :maxdepth: 1 - IntrinX86_128 - IntrinX86_256 - IntrinArm64_128 - IntrinArm64_256 + modules/src/IntrinX86_128 + modules/src/IntrinX86_256 + modules/src/IntrinArm64_128 + modules/src/IntrinArm64_256 SLEEF ~~~~~ @@ -43,7 +43,7 @@ See https://sleef.org/ for more information. .. toctree:: :maxdepth: 1 - SLEEF + modules/src/SLEEF Utilities @@ -52,7 +52,7 @@ Utilities .. toctree:: :maxdepth: 1 - Arch + modules/src/Arch Indices and tables diff --git a/lint/EverythingTested.py b/lint/EverythingTested.py index 1dcb624..aef17d4 100755 --- a/lint/EverythingTested.py +++ b/lint/EverythingTested.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import os import sys from pathlib import Path @@ -9,21 +8,20 @@ TEST_DIR = PROJECT_DIR / "test" -# list all tests from mason -import compile as ProjectScript +try: + import tomllib +except ModuleNotFoundError: + import pip._vendor.tomli as tomllib -mason_tests = ProjectScript.Project(PROJECT_DIR).get_tests() -mason_tests = [TEST_DIR / t for t in mason_tests] +with open(PROJECT_DIR / "Mason.toml", "rb") as f: + toml_data = tomllib.load(f) + +# read the mason tests from the toml +mason_tests = [TEST_DIR / t for t in toml_data["brick"]["tests"]] # list all .chpl files in TEST_DIR files = TEST_DIR.glob("**/*.chpl") -# exclude cmake dir -cmake_dir = TEST_DIR / "cmake" -files = [ - f for f in files if os.path.commonprefix((cmake_dir, f)) != str(cmake_dir) -] - # exclude TestHelpers.chpl TestHelpers = "TestHelpers.chpl" files = [f for f in files if f.name != TestHelpers] diff --git a/prereqs/cvl/Makefile b/prereqs/cvl/Makefile new file mode 100644 index 0000000..8171a32 --- /dev/null +++ b/prereqs/cvl/Makefile @@ -0,0 +1,24 @@ +ARCH := $(shell uname -m) + +X86_ARGS := --ccflags=-msse4.1 --ccflags=-mavx2 --ccflags=-mfma +ARM_ARGS := --ccflags=-march=armv8.2-a+fp16 + +FLAGS := +ifeq ($(ARCH),x86_64) + FLAGS += $(X86_ARGS) +else ifeq ($(ARCH),aarch64) + FLAGS += $(ARM_ARGS) +else ifeq ($(ARCH),arm64) + FLAGS += $(ARM_ARGS) +endif + +.PHONY: all +all: + @if [ "$(ARCH)" != "x86_64" ] && [ "$(ARCH)" != "aarch64" ] && [ "$(ARCH)" != "arm64" ]; then \ + echo "Unsupported architecture for CVL: $(ARCH)"; \ + exit 1; \ + fi + +.PHONY: printchplflags +printchplflags: + $(info $(FLAGS)) diff --git a/third-party/sleef/.gitignore b/prereqs/sleef/.gitignore similarity index 100% rename from third-party/sleef/.gitignore rename to prereqs/sleef/.gitignore diff --git a/prereqs/sleef/Makefile b/prereqs/sleef/Makefile new file mode 100644 index 0000000..2d48010 --- /dev/null +++ b/prereqs/sleef/Makefile @@ -0,0 +1,21 @@ +SLEEF_DIR := $(shell pwd)/sleef-install +OS := $(shell uname -s) + +SLEEF_ARGS := --set useSLEEF --set SLEEF_INSTALL='$(SLEEF_DIR)' +ifeq ($(OS),Linux) + SLEEF_ARGS += --ccflags=-Wno-unused-command-line-argument --ccflags=-no-pie --ldflags=-no-pie +endif + +.PHONY: all +all: $(SLEEF_DIR)/lib/libsleef.a + +$(SLEEF_DIR)/lib/libsleef.a: + ./install.sh + +.PHONY: printchplflags +printchplflags: + $(info $(SLEEF_ARGS)) + +.PHONY: clean +clean: + ./clean.sh diff --git a/third-party/sleef/clean.sh b/prereqs/sleef/clean.sh similarity index 100% rename from third-party/sleef/clean.sh rename to prereqs/sleef/clean.sh diff --git a/third-party/sleef/install.sh b/prereqs/sleef/install.sh similarity index 100% rename from third-party/sleef/install.sh rename to prereqs/sleef/install.sh diff --git a/src/IntrinArm64_256.chpl b/src/IntrinArm64_256.chpl index cadc9f2..d1c8965 100644 --- a/src/IntrinArm64_256.chpl +++ b/src/IntrinArm64_256.chpl @@ -60,6 +60,7 @@ module IntrinArm64_256 { inline proc type splat(x: laneType): vecType do return new vecType(implVecType.splat(x), implVecType.splat(x)); + @chplcheck.ignore("UnusedFormal") inline proc type set(xs...): vecType do compilerError("Not implemented"); inline proc type loada(x: c_ptrConst(laneType)): vecType do diff --git a/test/ShiftHalts.chpl b/test/ShiftHalts.chpl index 4a9db97..e64789c 100644 --- a/test/ShiftHalts.chpl +++ b/test/ShiftHalts.chpl @@ -24,10 +24,21 @@ config const testcase = 0; param numTests = /*procs*/14 * /*types*/8; +proc getEnvs(envs: [] string, toForward: [] string) { + use List, OS.POSIX; + var result = new list(envs); + for e in toForward { + var v = getenv(e.c_str()); + if v != nil { + result.pushBack(e + "=" + string.createCopyingBuffer(v)); + } + } + return result.toArray(); +} + proc main(args: [] string) { - if args.size > 1 then { + if args.size > 1 then return 1; // don't accept any args - } if testcase == 0 { var f = openMemFile(); var w = f.writer(); @@ -36,8 +47,12 @@ proc main(args: [] string) { // https://github.com/chapel-lang/chapel/issues/15497 const execname = args[0].stripSuffix("_real"); var p = spawn([execname, "-nl1", "--testcase="+i:string], - stdout=pipeStyle.pipe, stderr=pipeStyle.pipe); - // stdout=pipeStyle.pipe, stderr=pipeStyle.stdout); + stdout=pipeStyle.pipe, stderr=pipeStyle.pipe, + // stdout=pipeStyle.pipe, stderr=pipeStyle.stdout); + env=getEnvs(["CHPL_RT_UNWIND=0"], + ["GASNET_SPAWNFN", "GASNET_ROUTE_OUTPUT", + "GASNET_QUIET", "GASNET_MASTERIP", + "GASNET_WORKERIP", "CHPL_RT_OVERSUBSCRIBED"])); p.wait(); var stdout, stderr: string; p.stdout.readAll(stdout); diff --git a/test/cmake/.gitignore b/test/cmake/.gitignore deleted file mode 100644 index bcdff71..0000000 --- a/test/cmake/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build -install diff --git a/test/cmake/ExampleProject/CMakeLists.txt b/test/cmake/ExampleProject/CMakeLists.txt deleted file mode 100644 index 2c2f566..0000000 --- a/test/cmake/ExampleProject/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -find_package(chpl REQUIRED) - -project(ExampleProject LANGUAGES CHPL) -add_executable(ExampleProject main.chpl) -install(TARGETS ExampleProject DESTINATION bin) -install(PROGRAMS "${PROJECT_BINARY_DIR}/ExampleProject_real" DESTINATION bin OPTIONAL) - -set(CVL_SOURCE_DIR "" CACHE PATH "Path to the CVL source directory") - - -find_package(CVL CONFIG HINTS ${CVL_SOURCE_DIR}) -if (NOT CVL_FOUND) - message("CVL not found, cloning it...") - include(FetchContent) - FetchContent_Declare( - CVL - GIT_REPOSITORY https://github.com/jabraham17/cvl.git - GIT_BRANCH main - GIT_TAG main - GIT_SHALLOW TRUE - ) - FetchContent_MakeAvailable(CVL) - FetchContent_GetProperties(CVL SOURCE_DIR CVL_SOURCE_DIR_FETCHED) - find_package(CVL REQUIRED CONFIG HINTS ${CVL_SOURCE_DIR_FETCHED}) -endif() -target_link_libraries(ExampleProject PRIVATE cvl) diff --git a/test/cmake/ExampleProject/main.chpl b/test/cmake/ExampleProject/main.chpl deleted file mode 100644 index 3823c7f..0000000 --- a/test/cmake/ExampleProject/main.chpl +++ /dev/null @@ -1,6 +0,0 @@ -use CVL; - -proc main() { - var x: vector(real, 4) = (1.0, 2.0, 3.0, 4.0); - writeln(x); -} diff --git a/test/cmake/testExampleProject.sh b/test/cmake/testExampleProject.sh deleted file mode 100755 index c70ff89..0000000 --- a/test/cmake/testExampleProject.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env bash - -set -e - -CURRENT_DIR=$(cd $(dirname ${BASH_SOURCE[0]}) ; pwd) -EXAMPLE_PROJECT_DIR="${CURRENT_DIR}/ExampleProject" -BUILD_DIR="${EXAMPLE_PROJECT_DIR}/build" -INSTALL_DIR="${EXAMPLE_PROJECT_DIR}/install" - -function build() { - local cmake_cfg_args=$1 - local cmake_build_args=$2 - set -x - - mkdir -p "${BUILD_DIR}" - cmake -B "${BUILD_DIR}" "${EXAMPLE_PROJECT_DIR}" ${cmake_cfg_args} - cmake --build "${BUILD_DIR}" ${cmake_build_args} - cmake --install "${BUILD_DIR}" --prefix "${INSTALL_DIR}" - - set +x -} -function run() { - set -x - - # Check if the executable is built - if [[ ! -f "${INSTALL_DIR}/bin/ExampleProject" ]]; then - echo "Error: ExampleProject executable not found in ${INSTALL_DIR}/bin/" - exit 1 - fi - - # Run the executable to ensure it works - "${INSTALL_DIR}/bin/ExampleProject" -nl 1 - - set +x -} -function clean() { - set -x - rm -rf "${BUILD_DIR}" "${INSTALL_DIR}" - set +x -} -function check_no_deps() { - if [[ -d "${BUILD_DIR}/_deps" ]]; then - echo "Error: _deps directory should not exist after build." - exit 1 - fi -} -function check_deps() { - if [[ ! -d "${BUILD_DIR}/_deps" ]]; then - echo "Error: _deps directory should exist after build." - exit 1 - fi -} - -clean - -# -# Test that we can pass CVL_DIR to the CMakeLists.txt -# -build "-DCVL_DIR=${CURRENT_DIR}/../../cmake" "--target ExampleProject" -run -check_no_deps -clean - -# -# Test that we can pass CVL_SOURCE_DIR to the CMakeLists.txt -# -build "-DCVL_SOURCE_DIR=${CURRENT_DIR}/../.." "--target ExampleProject" -run -check_no_deps -clean - -# -# Test that we can add thr package to the cmake prefix path -# -build "-DCMAKE_PREFIX_PATH=${CURRENT_DIR}/../../cmake" "--target ExampleProject" -run -check_no_deps -clean - -# -# Test that we can fetch the package when it can't be found -# -build "" "--target ExampleProject" -run -check_deps -clean diff --git a/util/bench.py b/util/bench.py index cf58d05..a304a7e 100755 --- a/util/bench.py +++ b/util/bench.py @@ -14,10 +14,24 @@ import tempfile import re import os +from contextlib import contextmanager +import shutil + + +@contextmanager +def cd(path): + """Context manager for changing the current working directory""" + old_dir = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(old_dir) class Language(str, Enum): CHPL = "chpl" + MASON = "mason" C_GCC = "c-gcc" CPP_GCC = "cpp-gcc" C_CLANG = "c-clang" @@ -25,18 +39,25 @@ class Language(str, Enum): RUST = "rust" FORTRAN = "fortran" - def get_compiler(self) -> str: + def get_compiler(self) -> List[str]: m = { - Language.CHPL: "chpl", - Language.C_GCC: "gcc", - Language.CPP_GCC: "g++", - Language.C_CLANG: "clang", - Language.CPP_CLANG: "clang++", - Language.RUST: "rustc", - Language.FORTRAN: "gfortran", + Language.CHPL: ["chpl"], + Language.MASON: ["mason", "build", "--show", "--release", "--"], + Language.C_GCC: ["gcc"], + Language.CPP_GCC: ["g++"], + Language.C_CLANG: ["clang"], + Language.CPP_CLANG: ["clang++"], + Language.RUST: ["rustc"], + Language.FORTRAN: ["gfortran"], } return m[self] + def get_run_command(self, executable) -> List[str]: + if self == Language.MASON: + return ["mason", "run", "--"] + else: + return [executable] + class Stats(BaseModel): n: int @@ -49,8 +70,9 @@ class Stats(BaseModel): class BenchmarkVersion(BaseModel): name: str - files: List[str] language: Language + files: List[str] = Field(default_factory=list) + directory: Optional[str] = None compopts: List[str] = Field(default_factory=list) execopts: List[str] = Field(default_factory=list) execopts_small: Optional[List[str]] = Field( @@ -59,13 +81,6 @@ class BenchmarkVersion(BaseModel): measure: List[str] = Field(default_factory=list) arch: List[str] = Field(default_factory=list) - def resolve_compopts(self, cvl_options: Optional[str] = None): - # if CVL_OPTIONS in the compopts, remove it and add the CVL_OPTIONS - if cvl_options and "CVL_OPTIONS" in self.compopts: - self.compopts.remove("CVL_OPTIONS") - self.compopts.extend(cvl_options.split()) - return self.compopts - class BenchmarkConfig(BaseModel): name: str @@ -115,7 +130,12 @@ def run( measure_regexes[measure] = re.compile(measure) self.measurements[measure] = [] - files = [str(self.benchmark_dir / f) for f in self.version.files] + files = self.version.files + directory = ( + self.benchmark_dir / self.version.directory + if self.version.directory + else self.benchmark_dir + ) compopts = self.version.compopts execopts = ( self.version.execopts @@ -133,23 +153,46 @@ def run( compiler = self.version.language.get_compiler() - compile_cmd = ( - [compiler] + compopts + files + ["-o", str(executable_path)] - ) + if self.version.language == Language.MASON: + compile_cmd = compiler + compopts + files + else: + compile_cmd = ( + compiler + compopts + files + ["-o", str(executable_path)] + ) cc_str = " ".join(compile_cmd) print(f"Compiling {self.config.name}::{self.version.name} ({cc_str})") try: - subprocess.run( - compile_cmd, check=True, capture_output=True, text=True - ) + with cd(directory): + subprocess.run( + compile_cmd, + check=True, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) except subprocess.CalledProcessError as e: - print(f"Compilation failed: {e.stderr}", file=sys.stderr) + print(f"Compilation failed: {e.stdout}", file=sys.stderr) return False + # move the build artifact to the executable path if it's not already + # there (e.g. for mason) + if self.version.language == Language.MASON: + mason_exec_name = directory.name + mason_exec_path = directory / "target" / "release" / mason_exec_name + shutil.move(mason_exec_path, executable_path) + if mason_exec_path.with_name(mason_exec_name + "_real").exists(): + shutil.move( + mason_exec_path.with_name(mason_exec_name + "_real"), + executable_path.with_name(executable_name + "_real"), + ) + run_cmd = [str(executable_path)] - if self.version.language == Language.CHPL: + if ( + self.version.language == Language.CHPL + or self.version.language == Language.MASON + ): run_cmd += ["-nl1"] run_cmd += execopts @@ -161,9 +204,10 @@ def run( for trial in range(trials): print(f"Trial {trial + 1}/{trials}") start_time = time.time() - cp = subprocess.run( - run_cmd, check=True, capture_output=True, text=True - ) + with cd(directory): + cp = subprocess.run( + run_cmd, check=True, capture_output=True, text=True + ) end_time = time.time() elapsed_time = end_time - start_time if "RUNTIME" in self.measurements: @@ -229,7 +273,6 @@ def parse_args() -> argparse.Namespace: + "Format: benchmark::version or benchmark. " + "Can be specified multiple times.", ) - parser.add_argument("--cvl-options", type=str, default="") parser.add_argument("--scratch", type=Path, default=None) parser.add_argument( "--trials", @@ -355,13 +398,10 @@ def main(): benchmark_dir = Path(args.schema).parent runners = {} - cvl_options = args.cvl_options - for benchmark in schema.benchmarks: for version in benchmark.versions: full_name = f"{benchmark.name}::{version.name}" if should_run_benchmark(benchmark, version, args.filter): - version.resolve_compopts(cvl_options) runners[full_name] = BenchmarkRun( benchmark_dir, benchmark, version ) diff --git a/util/examples.sh b/util/examples.sh deleted file mode 100755 index c0f432b..0000000 --- a/util/examples.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -PROJECT_DIR=$(cd $(dirname $0); cd ..; pwd) - -CVL_OPTIONS=$($PROJECT_DIR/compile.py --sleef) -if [[ $? -ne 0 ]]; then - echo "Error: Failed to determine CVL options." - exit 1 -fi - -function build_and_run() { - local chpl_file=$1 - local compopts=$2 - - local basename=$(basename "$chpl_file" .chpl) - - echo "Compiling: $basename with options: '$compopts'" - chpl $chpl_file -o "$PROJECT_DIR/target/example/$basename" $CVL_OPTIONS - if [[ $? -ne 0 ]]; then - echo "Error: Compilation of $basename failed." - exit 1 - fi - - echo "Running: $basename" - "$PROJECT_DIR/target/example/$basename" -nl1 - if [[ $? -ne 0 ]]; then - echo "Error: Example $basename failed with exit code $res" - exit $res - fi - echo "" -} - - -mkdir -p "$PROJECT_DIR/target/example" -EXAMPLES=$($PROJECT_DIR/compile.py --examples) - -for example in $EXAMPLES; do - file_path="$PROJECT_DIR/example/$example" - # if a compopts file exists, compile for each one - compopts_file="${file_path%.chpl}.compopts" - if [[ -f "$compopts_file" ]]; then - while IFS= read -r compopts || [[ -n "$compopts" ]]; do - # skip empty lines and comments - if [[ -z "$compopts" || "$compopts" =~ ^# ]]; then - continue - fi - build_and_run "$file_path" "$compopts" - done < "$compopts_file" - else - build_and_run "$file_path" "" - fi -done diff --git a/util/lint.sh b/util/lint.sh index 13a2d0b..095478c 100755 --- a/util/lint.sh +++ b/util/lint.sh @@ -9,3 +9,8 @@ set -e (set -x && $PROJECT_DIR/lint/EverythingTested.py) (set -x && $PROJECT_DIR/lint/OperatorsUpToDate.sh) + +# TODO: re-enable this once docs are complete +# chpl_home=$(chpl --print-chpl-home) +# TO_CHECK=$(find src -name "*.chpl") +# (set -x && CHPL_HOME=$chpl_home $chpl_home/tools/chpldoc/findUndocumentedSymbols --ci $TO_CHECK) diff --git a/util/localRegistry.sh b/util/localRegistry.sh new file mode 100755 index 0000000..e00c4af --- /dev/null +++ b/util/localRegistry.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +PROJECT_DIR=$(cd $(dirname ${BASH_SOURCE[0]}) ; cd ..; pwd) +REG=$PROJECT_DIR/.registry +REG_NAME="local-registry" +MASON_HOME=$(mason env | grep MASON_HOME | cut -d: -f2 | tr -d ' ') + +if [[ -d $REG ]]; then + echo "Using existing local registry at $REG" +else + rm -rf $MASON_HOME/$REG_NAME + (cd $PROJECT_DIR && mkdir -p $REG && git init $REG) +fi + +dummyVersion=0.0.0 +dummyTag=v$dummyVersion + +# create the dummy tag, if it already exists, remove it and create it again +if (cd $PROJECT_DIR && git rev-parse $dummyTag >/dev/null 2>&1); then + echo "Dummy tag $dummyTag already exists, deleting it and creating it again" + (cd $PROJECT_DIR && git tag -d $dummyTag) +fi +(cd $PROJECT_DIR && git tag $dummyTag) + +# copy the toml to the registry as dummyVersion.toml, then rewrite the source +# and version +mkdir -p $REG/Bricks/CVL/ +cp $PROJECT_DIR/Mason.toml $REG/Bricks/CVL/$dummyVersion.toml +sed -E -e "s|source\s*=\s*\".*\"|source=\"$PROJECT_DIR\"|" -e "s|version\s*=\s*\".*\"|version=\"$dummyVersion\"|" $REG/Bricks/CVL/$dummyVersion.toml > $REG/Bricks/CVL/$dummyVersion.tmp.toml +mv $REG/Bricks/CVL/$dummyVersion.tmp.toml $REG/Bricks/CVL/$dummyVersion.toml + +# commit the new entry +(cd $REG && git add . && git commit -m "Added $dummyTag.toml for local registry") + +# clear the old repo +rm -rf $MASON_HOME/src/CVL-$dummyVersion + +export MASON_REGISTRY="local-registry|$REG" diff --git a/util/test.sh b/util/test.sh deleted file mode 100755 index 35b0219..0000000 --- a/util/test.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -PROJECT_DIR=$(cd $(dirname $0); cd ..; pwd) - -CVL_OPTIONS=$($PROJECT_DIR/compile.py --arch-compopts --sleef) -if [[ $? -ne 0 ]]; then - echo "Error: Failed to determine CVL options." - exit 1 -fi - -# Set MAX_LOCALES if specified in environment -rm -f $PROJECT_DIR/.MAX_LOCALES -if [[ ! -z "$MAX_LOCALES" ]]; then - echo "$MAX_LOCALES" > $PROJECT_DIR/.MAX_LOCALES -fi - -# --setComm works around a mason bug where it always defaults to `none` -(cd $PROJECT_DIR && set -x && \ - mason test --show --keep-binary \ - --setComm=$($(chpl --print-chpl-home)/util/chplenv/chpl_comm.py) \ - -- \ - $@ \ - $CVL_OPTIONS \ - --set CVL.implementationWarnings=false \ - | tee $PROJECT_DIR/test.log \ -) - -rm -f $PROJECT_DIR/.MAX_LOCALES - -# check the last line of test.log, if it starts with OK, then the test passed -# this is required because mason exits with 1 if a test is skipped -if [[ "$(tail -n 1 $PROJECT_DIR/test.log)" == "OK"* ]]; then - exit 0 -else - exit 1 -fi diff --git a/util/testCMake.sh b/util/testCMake.sh deleted file mode 100755 index d07e76c..0000000 --- a/util/testCMake.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -PROJECT_DIR=$(cd $(dirname $0); cd ..; pwd) - -$PROJECT_DIR/test/cmake/testExampleProject.sh || exit 1 diff --git a/util/tox.ini b/util/tox.ini index 9646314..362e7ab 100644 --- a/util/tox.ini +++ b/util/tox.ini @@ -7,5 +7,5 @@ deps = flake8 black commands = - flake8 --max-line-length 80 --extend-ignore=E203,E402 . --extend-exclude='.venv,third-party' - black -l 80 . --extend-exclude='.venv,third-party' + flake8 --max-line-length 80 --extend-ignore=E203,E402 . --extend-exclude='.venv,third-party,sleef' + black --check -l 80 . --extend-exclude='.venv,third-party,sleef'