Skip to content

Commit eb602a0

Browse files
committed
Add simple notebook
1 parent 4ca27af commit eb602a0

2 files changed

Lines changed: 267 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Jupyterlite deployment
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- master
9+
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
jobs:
16+
build:
17+
runs-on: ubuntu-24.04
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v6
21+
- uses: mamba-org/setup-micromamba@v3
22+
with:
23+
cache-environment: true
24+
post-cleanup: 'all'
25+
environment-name: jupyterlite-builer
26+
create-args: jupyter jupyterlite-core jupyterlite-xeus
27+
- name: Build WASM environment
28+
run: |
29+
micromamba create -p ./wasm-env \
30+
--platform=emscripten-wasm32 \
31+
--channel https://prefix.dev/emscripten-forge-4x \
32+
--channel https://prefix.dev/conda-forge \
33+
xeus-cpp=0.10
34+
- name: Build Jupyterlite distribution
35+
run: |
36+
micromamba run -n jupyterlite-builer \
37+
jupyter lite build \
38+
--XeusAddon.prefix=./wasm-env \
39+
--contents include/ \
40+
--contents notebooks/ \
41+
--output-dir ./dist
42+
- name: Upload artifact
43+
uses: actions/upload-pages-artifact@v3
44+
with:
45+
path: ./dist
46+
47+
deploy:
48+
needs: build
49+
if: github.ref == 'refs/heads/master'
50+
permissions:
51+
pages: write
52+
id-token: write
53+
environment:
54+
name: github-pages
55+
url: ${{ steps.deployment.outputs.page_url }}
56+
runs-on: ubuntu-24.04
57+
steps:
58+
- name: Deploy to GitHub Pages
59+
id: deployment
60+
uses: actions/deploy-pages@v4

notebooks/simple.ipynb

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "2efd7be2-5ea7-42cb-a2e2-9ddb409bc893",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"#include <cstddef>\n",
11+
"#include <vector>\n",
12+
"#include <random>\n",
13+
"#include <iostream>\n",
14+
"\n",
15+
"#include <xsimd/xsimd.hpp>"
16+
]
17+
},
18+
{
19+
"cell_type": "markdown",
20+
"id": "6f498bff-4366-4e1c-ab25-3d3589740e78",
21+
"metadata": {},
22+
"source": [
23+
"Comparing two implementation of element wise mean."
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": null,
29+
"id": "cf6b2c85-1427-49a3-8bef-0340601319e8",
30+
"metadata": {},
31+
"outputs": [],
32+
"source": [
33+
"std::vector<double> random_vector(std::size_t n)\n",
34+
"{\n",
35+
" static std::mt19937 gen(42);\n",
36+
" std::uniform_real_distribution<double> dist(0.0, 1.0);\n",
37+
" std::vector<double> v(n);\n",
38+
" for (auto& x : v)\n",
39+
" {\n",
40+
" x = dist(gen);\n",
41+
" }\n",
42+
" return v;\n",
43+
"}"
44+
]
45+
},
46+
{
47+
"cell_type": "code",
48+
"execution_count": null,
49+
"id": "a2ab6177-60e2-4d65-b323-51a6a21ad530",
50+
"metadata": {},
51+
"outputs": [],
52+
"source": [
53+
"std::vector<double> mean_scalar(const std::vector<double>& a, const std::vector<double>& b)\n",
54+
"{\n",
55+
" std::size_t size = a.size();\n",
56+
" std::vector<double> res(size);\n",
57+
" for (std::size_t i = 0; i < size; ++i)\n",
58+
" {\n",
59+
" res[i] = (a[i] + b[i]) / 2;\n",
60+
" }\n",
61+
" return res;\n",
62+
"}"
63+
]
64+
},
65+
{
66+
"cell_type": "code",
67+
"execution_count": null,
68+
"id": "082ed2cd-273a-4c3c-a206-03b1efe49482",
69+
"metadata": {},
70+
"outputs": [],
71+
"source": [
72+
"std::vector<double> mean_simd(const std::vector<double>& a, const std::vector<double>& b)\n",
73+
"{\n",
74+
" using b_type = xsimd::batch<double>;\n",
75+
" std::size_t inc = b_type::size;\n",
76+
" std::size_t size = a.size();\n",
77+
" std::vector<double> res(size);\n",
78+
"\n",
79+
" // size for which the vectorization is possible\n",
80+
" std::size_t vec_size = size - size % inc;\n",
81+
" for (std::size_t i = 0; i < vec_size; i += inc)\n",
82+
" {\n",
83+
" b_type avec = b_type::load_unaligned(&a[i]);\n",
84+
" b_type bvec = b_type::load_unaligned(&b[i]);\n",
85+
" b_type rvec = (avec + bvec) / 2;\n",
86+
" rvec.store_unaligned(&res[i]);\n",
87+
" }\n",
88+
" // Remaining part that cannot be vectorize\n",
89+
" for (std::size_t i = vec_size; i < size; ++i)\n",
90+
" {\n",
91+
" res[i] = (a[i] + b[i]) / 2;\n",
92+
" }\n",
93+
" return res;\n",
94+
"}"
95+
]
96+
},
97+
{
98+
"cell_type": "code",
99+
"execution_count": null,
100+
"id": "5959864d",
101+
"metadata": {},
102+
"outputs": [],
103+
"source": [
104+
"// Print v[begin:end] as grayscale ASCII blocks (dark = 0, light = 1).\n",
105+
"void print_grayscale(const std::vector<double>& v, std::size_t begin, std::size_t end)\n",
106+
"{\n",
107+
" for (std::size_t i = begin; i < end; ++i)\n",
108+
" {\n",
109+
" // map value in [0, 1] to a 24-bit truecolor gray (256 levels)\n",
110+
" int gray = static_cast<int>(v[i] * 255);\n",
111+
" std::cout << \"\\033[38;2;\" << gray << \";\" << gray << \";\" << gray << \"m█\";\n",
112+
" }\n",
113+
" std::cout << \"\\033[0m\\n\";\n",
114+
"}"
115+
]
116+
},
117+
{
118+
"cell_type": "code",
119+
"execution_count": null,
120+
"id": "2068e201",
121+
"metadata": {},
122+
"outputs": [],
123+
"source": [
124+
"std::size_t n = 1000;\n",
125+
"std::vector<double> const a = random_vector(n);\n",
126+
"std::vector<double> const b = random_vector(n);"
127+
]
128+
},
129+
{
130+
"cell_type": "code",
131+
"execution_count": null,
132+
"id": "9d5a7adc-5b55-4224-a4ca-5e438d1fc4d4",
133+
"metadata": {},
134+
"outputs": [],
135+
"source": [
136+
"auto const res_simd = mean_simd(a, b);"
137+
]
138+
},
139+
{
140+
"cell_type": "code",
141+
"execution_count": null,
142+
"id": "d279cd74-c397-4ea8-af15-3745f043f656",
143+
"metadata": {},
144+
"outputs": [],
145+
"source": [
146+
"auto const res_scalar = mean_scalar(a, b);"
147+
]
148+
},
149+
{
150+
"cell_type": "markdown",
151+
"id": "a04ae145",
152+
"metadata": {},
153+
"source": [
154+
"Each block is a value in `[0, 1]` shown as a grayscale shade (dark = low, light = high). The vector is drawn in chunks of 100, each chunk stacking input `a`, the SIMD mean, the scalar mean, and input `b`. The two mean rows should look identical, each sitting between its inputs."
155+
]
156+
},
157+
{
158+
"cell_type": "code",
159+
"execution_count": null,
160+
"id": "59ca84ad-8b97-4523-af0d-d3eca01b41d0",
161+
"metadata": {},
162+
"outputs": [],
163+
"source": [
164+
"std::size_t const width = 100;\n",
165+
"for (std::size_t begin = 0; begin < n; begin += width)\n",
166+
"{\n",
167+
" std::size_t end = std::min(begin + width, n);\n",
168+
" std::cout << \"a: \";\n",
169+
" print_grayscale(a, begin, end);\n",
170+
" std::cout << \"simd: \";\n",
171+
" print_grayscale(res_simd, begin, end);\n",
172+
" std::cout << \"scalar: \";\n",
173+
" print_grayscale(res_scalar, begin, end);\n",
174+
" std::cout << \"b: \";\n",
175+
" print_grayscale(b, begin, end);\n",
176+
" std::cout << \"\\n\";\n",
177+
"}"
178+
]
179+
},
180+
{
181+
"cell_type": "code",
182+
"execution_count": null,
183+
"id": "90b86fb4-0426-43fd-b5fc-8626ef8732a5",
184+
"metadata": {},
185+
"outputs": [],
186+
"source": []
187+
}
188+
],
189+
"metadata": {
190+
"kernelspec": {
191+
"display_name": "C++17",
192+
"language": "cpp",
193+
"name": "xcpp17"
194+
},
195+
"language_info": {
196+
"codemirror_mode": "text/x-c++src",
197+
"file_extension": ".cpp",
198+
"mimetype": "text/x-c++src",
199+
"name": "C++",
200+
"nbconvert_exporter": "",
201+
"pygments_lexer": "",
202+
"version": "cxx17"
203+
}
204+
},
205+
"nbformat": 4,
206+
"nbformat_minor": 5
207+
}

0 commit comments

Comments
 (0)