-
Notifications
You must be signed in to change notification settings - Fork 437
Create executable notebook for simple vector add example #3047
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # Tutorials | ||
|
|
||
| This folder contains tutorials introducing Highway. The | ||
| tutorials are in Jupyter notebooks. They can be run on | ||
| your own machine, but can also be run through a web browser | ||
| on [Google Colab](https://colab.research.google.com) or on | ||
| [MyBinder](https://mybinder.org/) or other cloud services that | ||
| allow one to execute Jupyter Notebooks. | ||
|
|
||
| - Vector Add | ||
| [](https://colab.research.google.com/github/google/highway/tutorials/vector_add.ipynb) | ||
| [](https://mybinder.org/v2/gh/google/highway/tutorials/vector_add.ipnyb/HEAD) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,328 @@ | ||
| { | ||
| "nbformat": 4, | ||
| "nbformat_minor": 0, | ||
| "metadata": { | ||
| "colab": { | ||
| "provenance": [] | ||
| }, | ||
| "kernelspec": { | ||
| "name": "python3", | ||
| "display_name": "Python 3" | ||
| }, | ||
| "language_info": { | ||
| "name": "python" | ||
| } | ||
| }, | ||
| "cells": [ | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Copyright 2026 Google LLC\n", | ||
| "SPDX-License-Identifier: Apache-2.0\n", | ||
| "\n", | ||
| "Licensed under the Apache License, Version 2.0 (the \"License\");\n", | ||
| "you may not use this file except in compliance with the License.\n", | ||
| "You may obtain a copy of the License at\n", | ||
| "\n", | ||
| " http://www.apache.org/licenses/LICENSE-2.0\n", | ||
| "\n", | ||
| "Unless required by applicable law or agreed to in writing, software\n", | ||
| "distributed under the License is distributed on an \"AS IS\" BASIS,\n", | ||
| "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", | ||
| "See the License for the specific language governing permissions and\n", | ||
| "limitations under the License" | ||
| ], | ||
| "metadata": { | ||
| "id": "YNknTdrHd024" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "First setup an environment to enable one to learn how to use Highway." | ||
| ], | ||
| "metadata": { | ||
| "id": "Si4d423YTtoJ" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "!apt update -qq;\n", | ||
| "!apt-get update -qq;\n", | ||
| "!apt update\n", | ||
| "!apt install cmake gcc g++ git libatomic1 libgtest-dev ninja-build\n", | ||
| "!apt-get upgrade" | ||
| ], | ||
| "metadata": { | ||
| "id": "mZAXwNtqT6Pu" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Now get the highway code and install Highway. This may take about 10 minutes. To not extend build time further, do not build tests and examples." | ||
| ], | ||
| "metadata": { | ||
| "id": "DvphHZwhVSA5" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "#!git clone https://github.com/google/highway\n", | ||
| "%cd highway\n", | ||
| "!mkdir build\n", | ||
| "%cd build\n", | ||
| "!cmake -GNinja \\\n", | ||
| " -DHWY_ENABLE_TESTS=OFF \\\n", | ||
| " -DHWY_ENABLE_EXAMPLES=OFF \\\n", | ||
| " -DHWY_ENABLE_CONTRIB=ON \\\n", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall we disable CONTRIB to speed up the build? Also, if we were to build PPAs, how would those be referenced from the install step here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disabling CONTRIB can help. It may be helpful to give a choice of building or installing a PPA. Going through the steps of building can be helpful for someone to build on their own machine. Checking on PPAs at https://documentation.ubuntu.com/launchpad/user/reference/packaging/ppas/ppa/ Some people also use org-mode to create notebooks:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, agree it would be nice to set ENABLE_CONTRIB=OFF here :) Nice find with the PPA action! Would you like to send a separate PR adding that workflow for manual dispatch (by adding a workflow_dispatch section)? I'd be willing to run this after releases. |
||
| " -DCMAKE_INSTALL_PREFIX=/content/highway_install ..\n", | ||
| "!ninja\n", | ||
| "!ninja install\n", | ||
| "%cd ..\n", | ||
| "%cd .." | ||
| ], | ||
| "metadata": { | ||
| "id": "XJGOuRrHVX61" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [], | ||
| "metadata": { | ||
| "id": "TmL-d260daxu" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "As a first example, let us try out a program to do a vector addition." | ||
| ], | ||
| "metadata": { | ||
| "id": "I4JbTFcUeHrH" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "%%writefile vector_add.cpp\n", | ||
| "#include <stddef.h>\n", | ||
| "#include <stdint.h>\n", | ||
| "\n", | ||
| "#include <chrono>\n", | ||
| "#include <iostream>\n", | ||
| "#include <numeric>\n", | ||
| "#include <vector>\n", | ||
| "\n", | ||
| "float SumArray(const float* array, size_t count) {\n", | ||
| " float sum = 0;\n", | ||
| " for (size_t i = 0 ; i < count; i++) {\n", | ||
| " sum += array[i];\n", | ||
| " }\n", | ||
| " return sum;\n", | ||
| "}\n", | ||
| "\n", | ||
| "int main() {\n", | ||
| " const size_t count = 1025;\n", | ||
| " std::vector<float> data(count);\n", | ||
| " std::iota(data.begin(), data.end(), 1.0f);\n", | ||
| " //start timer\n", | ||
| " auto start = std::chrono::high_resolution_clock::now();\n", | ||
| " float sum = SumArray(data.data(), count);\n", | ||
| " //stop timer and print time and sum\n", | ||
| " auto stop = std::chrono::high_resolution_clock::now();\n", | ||
| " std::chrono::duration<double, std::milli> diff = stop - start;\n", | ||
| " std::cout << \"Execution time: \" << diff.count() << \" ms\" << std::endl;\n", | ||
| " std::cout << \"Sum: \" << sum << std::endl;\n", | ||
| "\n", | ||
| " return 0;\n", | ||
| "}" | ||
| ], | ||
| "metadata": { | ||
| "id": "eEuRa_9Qe29p" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Now compile and run this program with no optimization." | ||
| ], | ||
| "metadata": { | ||
| "id": "FUsIWK5nggb8" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "!g++ -std=c++17 -O0 -o vector_add.o -c vector_add.cpp\n", | ||
| "!g++ -o vectoradd vector_add.o\n", | ||
| "!./vector_add" | ||
| ], | ||
| "metadata": { | ||
| "id": "y4V99UFfgpau" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Now compile and run an optimized executable." | ||
| ], | ||
| "metadata": { | ||
| "id": "tsRbfP4Hi4SJ" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "!g++ -O3 vector_add.cpp -o vector_add\n", | ||
| "!./vector_add" | ||
| ], | ||
| "metadata": { | ||
| "id": "k5DgYSprip_0" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Now use Highway to do explicit vectorization." | ||
| ], | ||
| "metadata": { | ||
| "id": "QhhDEzBsjdjj" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "%%writefile vector_add_hwy.cpp\n", | ||
| "#include <stddef.h>\n", | ||
| "#include <stdint.h>\n", | ||
| "\n", | ||
| "#include <chrono>\n", | ||
| "#include <iostream>\n", | ||
| "#include <numeric>\n", | ||
| "#include <vector>\n", | ||
| "\n", | ||
| "\n", | ||
| "// >>>> for dynamic dispatch only, skip if you want static dispatch\n", | ||
| "\n", | ||
| "// First undef to prevent error when re-included.\n", | ||
| "#undef HWY_TARGET_INCLUDE\n", | ||
| "// For dynamic dispatch, specify the name of the current file (unfortunately\n", | ||
| "// __FILE__ is not reliable) so that foreach_target.h can re-include it.\n", | ||
| "// The absolute path seems to be required\n", | ||
| "#define HWY_TARGET_INCLUDE \"/content/vector_add_hwy.cpp\"\n", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's good practice to avoid absolute paths in includes. Just "vector_add_hwy"? |
||
| "// Generates code for each enabled target by re-including this source file.\n", | ||
| "#include \"hwy/foreach_target.h\" // IWYU pragma: keep\n", | ||
| "\n", | ||
| "// <<<< end of dynamic dispatch\n", | ||
| "//\n", | ||
| "#include \"hwy/highway.h\"\n", | ||
| "\n", | ||
| "HWY_BEFORE_NAMESPACE();\n", | ||
| "namespace hwy {\n", | ||
| "namespace HWY_NAMESPACE {\n", | ||
| "namespace hn = hwy::HWY_NAMESPACE;\n", | ||
| "\n", | ||
| "float SumArraySIMD(const float* HWY_RESTRICT array, size_t count) {\n", | ||
| " const hn::ScalableTag<float> d;\n", | ||
| " using V = hn::Vec<decltype(d)>;\n", | ||
| " V sum = hn::Zero(d);\n", | ||
| " size_t i = 0;\n", | ||
| " const size_t N = hn::Lanes(d);\n", | ||
| " if (count >= N) {\n", | ||
| " for (; i <= count - N; i += N) {\n", | ||
| " sum = hn::Add(sum, hn::LoadU(d, array + i));\n", | ||
| " }\n", | ||
| " }\n", | ||
| " float total = hn::ReduceSum(d, sum);\n", | ||
| " // Simple scalar remainder handling\n", | ||
| " for (; i < count; ++i) {\n", | ||
| " total += array[i];\n", | ||
| " }\n", | ||
| " return total;\n", | ||
| "}\n", | ||
| "\n", | ||
| "} // namespace HWY_NAMESPACE\n", | ||
| "} // namespace hwy\n", | ||
| "HWY_AFTER_NAMESPACE();\n", | ||
| "\n", | ||
| "#if HWY_ONCE\n", | ||
| "namespace hwy {\n", | ||
| "HWY_EXPORT(SumArraySIMD);\n", | ||
| "\n", | ||
| "float CallSumArraySIMD(const float* array, size_t count) {\n", | ||
| " return HWY_DYNAMIC_DISPATCH(SumArraySIMD)(array, count);\n", | ||
| "}\n", | ||
| "\n", | ||
| "} // namespace hwy\n", | ||
| "\n", | ||
| "int main() {\n", | ||
| " const size_t count = 1025;\n", | ||
| " std::vector<float> data(count);\n", | ||
| " std::iota(data.begin(), data.end(), 1.0f);\n", | ||
| " //start timer\n", | ||
| " auto start = std::chrono::high_resolution_clock::now();\n", | ||
| " float sum = hwy::CallSumArraySIMD(data.data(), count);\n", | ||
| " //stop timer and print time and sum\n", | ||
| " auto stop = std::chrono::high_resolution_clock::now();\n", | ||
| " std::chrono::duration<double, std::milli> diff = stop - start;\n", | ||
| " std::cout << \"Execution time: \" << diff.count() << \" ms\" << std::endl;\n", | ||
| " std::cout << \"Sum: \" << sum << std::endl;\n", | ||
| "\n", | ||
| " return 0;\n", | ||
| "}\n", | ||
| "#endif // HWY_ONCE" | ||
| ], | ||
| "metadata": { | ||
| "id": "ANEqe3CtkMTj" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Compile and run explicitly vectorized version." | ||
| ], | ||
| "metadata": { | ||
| "id": "TfsXskkcluH1" | ||
| } | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "source": [ | ||
| "!g++ -std=c++17 -O3 -I/content/highway_install/include -o vector_add_hwy.o -c vector_add_hwy.cpp\n", | ||
| "!g++ -o vector_add_hwy vector_add_hwy.o -L/content/highway_install/lib -lhwy_contrib -lhwy\n", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add -I/ for the above. |
||
| "!./vector_add_hwy" | ||
| ], | ||
| "metadata": { | ||
| "id": "_f93Lxefly6n" | ||
| }, | ||
| "execution_count": null, | ||
| "outputs": [] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "source": [ | ||
| "Try increasing the array size, then recompile and run the examples again. For what array size is the explicitly SIMD vectorized program faster than the program with O0 optimization? What about for O3 optimization?\n", | ||
| "\n", | ||
| "Ideally, make a plot showing execution time against array size for the program with O0 optimization, O3 optimization and explicitly vectorized using Highway." | ||
| ], | ||
| "metadata": { | ||
| "id": "JSd31IBzA1L6" | ||
| } | ||
| } | ||
| ] | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can add mention on how to run these locally?