diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e1648fd..40e10e26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,13 @@ endif() find_package(argparse REQUIRED) find_package(pugixml REQUIRED) +find_package(OpenMP) + +# Used to configure OpenMP kernels such that Cpp::loadlibrary knows where OpenMP library is +if (NOT WIN32) + list(GET OpenMP_CXX_LIBRARIES 0 FirstOpenMPLibrary) + get_filename_component(OpenMPLibraryDir "${FirstOpenMPLibrary}" DIRECTORY) +endif() # Configuration # ============= @@ -127,6 +134,9 @@ function(configure_kernel kernel) set(XEUS_CPP_PATH "$ENV{PATH}") set(XEUS_CPP_LD_LIBRARY_PATH "$ENV{LD_LIBRARY_PATH}") set(XEUS_CPP_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include) + if(${kernel} MATCHES "omp/$") + set(XEUS_CPP_OMP "${OpenMP_CXX_FLAGS}") + endif() endif() if (WIN32) string(REPLACE "\\" "/" kernel "${kernel}") @@ -163,6 +173,14 @@ configure_kernel("/share/jupyter/kernels/xcpp23/") configure_kernel("/share/jupyter/kernels/xc11/") configure_kernel("/share/jupyter/kernels/xc17/") configure_kernel("/share/jupyter/kernels/xc23/") +if(NOT EMSCRIPTEN) + configure_kernel("/share/jupyter/kernels/xcpp17-omp/") + configure_kernel("/share/jupyter/kernels/xcpp20-omp/") + configure_kernel("/share/jupyter/kernels/xcpp23-omp/") + configure_kernel("/share/jupyter/kernels/xc11-omp/") + configure_kernel("/share/jupyter/kernels/xc17-omp/") + configure_kernel("/share/jupyter/kernels/xc23-omp/") +endif() # Source files # ============ diff --git a/environment-dev.yml b/environment-dev.yml index a6a7cf58..d56a37c5 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -14,6 +14,7 @@ dependencies: - CppInterOp - pugixml - cpp-argparse + - llvm-openmp # Test dependencies - pytest - jupyter_kernel_test<0.8 diff --git a/notebooks/openmp-notebooks/hello_world.ipynb b/notebooks/openmp-notebooks/hello_world.ipynb new file mode 100644 index 00000000..3d23faef --- /dev/null +++ b/notebooks/openmp-notebooks/hello_world.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "73cbab37-71dd-477d-981b-f2ec28c01bd6", + "metadata": {}, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ef1cd58a-672c-4a6f-843a-6c88fc4911f3", + "metadata": {}, + "outputs": [], + "source": [ + "Cpp::LoadLibrary(\"libomp\");\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "c2b754ad-9553-4a42-b990-f990a9a269ed", + "metadata": {}, + "outputs": [], + "source": [ + "int main() {\n", + " int max_threads = omp_get_max_threads();\n", + "\n", + " printf(\"max threads: %d\\n\", max_threads);\n", + " omp_set_num_threads(max_threads);\n", + "\n", + "#pragma omp parallel\n", + " {\n", + " int id = omp_get_thread_num();\n", + " printf(\"Hello World from thread = %d with %d threads\\n\", id, omp_get_num_threads());\n", + " }\n", + "\n", + " printf(\"all done, with hopefully %d threads\\n\", max_threads);\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a37a13d4-fc82-496e-8f42-9e718a8c2aa0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "max threads: 8\n", + "Hello World from thread = 0 with 8 threads\n", + "Hello World from thread = 3 with 8 threads\n", + "Hello World from thread = 4 with 8 threads\n", + "Hello World from thread = 2 with 8 threads\n", + "Hello World from thread = 7 with 8 threads\n", + "Hello World from thread = 1 with 8 threads\n", + "Hello World from thread = 6 with 8 threads\n", + "Hello World from thread = 5 with 8 threads\n", + "all done, with hopefully 8 threads\n" + ] + } + ], + "source": [ + "main();" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "C++17 (xcpp+OpenMP)", + "language": "cpp", + "name": "xcpp17-omp" + }, + "language_info": { + "codemirror_mode": "text/x-c++src", + "file_extension": ".cpp", + "mimetype": "text/x-c++src", + "name": "C++", + "version": "17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/openmp-notebooks/linked_list.ipynb b/notebooks/openmp-notebooks/linked_list.ipynb new file mode 100644 index 00000000..607ceb18 --- /dev/null +++ b/notebooks/openmp-notebooks/linked_list.ipynb @@ -0,0 +1,234 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "156447d2-9279-45a0-890b-4e519d2c796b", + "metadata": {}, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "#include \n", + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c96fdeb0-817d-48c0-af8e-20a52947d60b", + "metadata": {}, + "outputs": [], + "source": [ + "#ifndef N\n", + "#define N 5\n", + "#endif\n", + "#ifndef FS\n", + "#define FS 38\n", + "#endif" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8da842e1-db02-49e0-929d-4e67cbc08172", + "metadata": {}, + "outputs": [], + "source": [ + "Cpp::LoadLibrary(\"libomp\");" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "22f97c49-78d1-496e-ac7c-978aed95331a", + "metadata": {}, + "outputs": [], + "source": [ + "struct node {\n", + " int data;\n", + " int fibdata;\n", + " struct node *next;\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b16b1e8a-8831-4b8d-9d57-09deeaaa88ee", + "metadata": {}, + "outputs": [], + "source": [ + "struct node *init_list(struct node *p);\n", + "void processwork(struct node *p);\n", + "int fib(int n);" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0ef8af6c-1d6f-4c68-84bc-3dd1d8092b06", + "metadata": {}, + "outputs": [], + "source": [ + "int fib(int n) {\n", + " int x, y;\n", + " if (n < 2) {\n", + " return (n);\n", + " } else {\n", + " x = fib(n - 1);\n", + " y = fib(n - 2);\n", + " return (x + y);\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1fa0307d-fdc9-4503-95cb-1c6448791354", + "metadata": {}, + "outputs": [], + "source": [ + "void processwork(struct node *p) {\n", + " int n, temp;\n", + " n = p->data;\n", + " temp = fib(n);\n", + "\n", + " p->fibdata = temp;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "03acb599-9329-49ff-8aff-c0902adb6c3c", + "metadata": {}, + "outputs": [], + "source": [ + "struct node *init_list(struct node *p) {\n", + " int i;\n", + " struct node *head = NULL;\n", + " struct node *temp = NULL;\n", + "\n", + " head = (struct node*) malloc(sizeof(struct node));\n", + " p = head;\n", + " p->data = FS;\n", + " p->fibdata = 0;\n", + " for (i = 0; i < N; i++) {\n", + " temp = (struct node*) malloc(sizeof(struct node));\n", + " p->next = temp;\n", + " p = temp;\n", + " p->data = FS + i + 1;\n", + " p->fibdata = i + 1;\n", + " }\n", + "\n", + " p->next = NULL;\n", + " return head;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "f2dfb41b-e55f-43c0-b7f6-546a1697acb1", + "metadata": {}, + "outputs": [], + "source": [ + "int main() {\n", + " double start, end;\n", + " struct node *p = NULL;\n", + " struct node *temp = NULL;\n", + " struct node *head = NULL;\n", + "\n", + " printf(\"Process linked list\\n\");\n", + " printf(\" Each linked list node will be processed by function 'processwork()'\\n\");\n", + " printf(\" Each ll node will compute %d fibonacci numbers beginning with %d\\n\", N, FS);\n", + "\n", + " omp_set_num_threads(omp_get_max_threads());\n", + "\n", + " p = init_list(p);\n", + " head = p;\n", + "\n", + " start = omp_get_wtime();\n", + "\n", + "#pragma omp parallel\n", + " {\n", + "#pragma omp master\n", + " printf(\"Threads: %d\\n\", omp_get_num_threads());\n", + "\n", + "#pragma omp single\n", + " {\n", + " p = head;\n", + " while (p) {\n", + "#pragma omp task firstprivate(p) // first private is required\n", + " {\n", + " processwork(p);\n", + " }\n", + " p = p->next;\n", + " }\n", + " }\n", + " }\n", + "\n", + " end = omp_get_wtime();\n", + " p = head;\n", + " while (p != NULL) {\n", + " printf(\"%d : %d\\n\", p->data, p->fibdata);\n", + " temp = p->next;\n", + " free(p);\n", + " p = temp;\n", + " }\n", + "\n", + " free(p);\n", + " printf(\"Compute Time: %f seconds\\n\", end - start);\n", + "\n", + " return 0;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "353e5dfd-fcae-43e6-97e3-ec98070811a1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Process linked list\n", + " Each linked list node will be processed by function 'processwork()'\n", + " Each ll node will compute 5 fibonacci numbers beginning with 38\n", + "Threads: 8\n", + "38 : 39088169\n", + "39 : 63245986\n", + "40 : 102334155\n", + "41 : 165580141\n", + "42 : 267914296\n", + "43 : 433494437\n", + "Compute Time: 2.617225 seconds\n" + ] + } + ], + "source": [ + "main();" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "C++17 (xcpp+OpenMP)", + "language": "cpp", + "name": "xcpp17-omp" + }, + "language_info": { + "codemirror_mode": "text/x-c++src", + "file_extension": ".cpp", + "mimetype": "text/x-c++src", + "name": "C++", + "version": "17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/openmp-notebooks/mandel.ipynb b/notebooks/openmp-notebooks/mandel.ipynb new file mode 100644 index 00000000..2d5f8a33 --- /dev/null +++ b/notebooks/openmp-notebooks/mandel.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "5059dbdd-821d-498a-8716-eb0fcf8a8f5f", + "metadata": {}, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "#include \n", + "#include \n", + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4e037323-fbc6-43c8-a17f-6044997bf49b", + "metadata": {}, + "outputs": [], + "source": [ + "Cpp::LoadLibrary(\"libomp\");" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8b66f96a-14ef-4f23-8024-bcfc42b31e4e", + "metadata": {}, + "outputs": [], + "source": [ + "#define NPOINTS 1000\n", + "#define MAXITER 1000" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d89dd57c-fe19-4233-a33a-df9b24fae98a", + "metadata": {}, + "outputs": [], + "source": [ + "int numoutside = 0;" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5c35c479-2f79-46b7-bc66-24be6b1694e0", + "metadata": {}, + "outputs": [], + "source": [ + "void testpoint(double creal, double cimag) {\n", + " // iterate z=z*z+c, until |z| > 2 when point is known to be outside set\n", + " // If loop count reaches MAXITER, point is considered to be inside the set\n", + "\n", + " double zreal, zimag, temp;\n", + " int iter;\n", + " zreal = creal;\n", + " zimag = cimag;\n", + "\n", + " for (iter = 0; iter < MAXITER; iter++) {\n", + " temp = (zreal * zreal) - (zimag * zimag) + creal;\n", + " zimag = zreal * zimag * 2 + cimag;\n", + " zreal = temp;\n", + " if ((zreal * zreal + zimag * zimag) > 4.0) {\n", + " numoutside++;\n", + " break;\n", + " }\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ea116fef-7d05-4e29-97a1-55c85c7241d8", + "metadata": {}, + "outputs": [], + "source": [ + "int main() {\n", + " int i, j;\n", + " double area, error, eps = 1.0e-5;\n", + " double cimag, creal;\n", + " // Loop over grid of points in the complex plane which contains the Mandelbrot set,\n", + " // testing each point to see whether it is inside or outside the set.\n", + "\n", + "#pragma omp parallel for private(eps)\n", + " for (i = 0; i < NPOINTS; i++) {\n", + " for (j = 0; j < NPOINTS; j++) {\n", + " creal = -2.0 + 2.5 * (double) (i) / (double) (NPOINTS) + eps;\n", + " cimag = 1.125 * (double) (j) / (double) (NPOINTS) + eps;\n", + " testpoint(creal, cimag);\n", + " }\n", + " }\n", + "\n", + " // Calculate area of set and error estimate and output the results\n", + " area = 2.0 * 2.5 * 1.125 * (double) (NPOINTS * NPOINTS - numoutside) / (double) (NPOINTS * NPOINTS);\n", + " error = area / (double) NPOINTS;\n", + "\n", + " printf(\"Area of Mandlebrot set = %12.8f +/- %12.8f\\n\", area, error);\n", + " printf(\"Correct answer should be around 1.510659\\n\");\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "39cf129c-8106-4e67-a2f1-1a7fff17cd38", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Area of Mandlebrot set = 3.80247750 +/- 0.00380248\n", + "Correct answer should be around 1.510659\n" + ] + } + ], + "source": [ + "main();" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "C++17 (xcpp+OpenMP)", + "language": "cpp", + "name": "xcpp17-omp" + }, + "language_info": { + "codemirror_mode": "text/x-c++src", + "file_extension": ".cpp", + "mimetype": "text/x-c++src", + "name": "C++", + "version": "17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/openmp-notebooks/openmp-demo.ipynb b/notebooks/openmp-notebooks/openmp-demo.ipynb new file mode 100644 index 00000000..fbc24f6f --- /dev/null +++ b/notebooks/openmp-notebooks/openmp-demo.ipynb @@ -0,0 +1,231 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "b0c15570-ee24-42ed-b61f-11a3fc858b2d", + "metadata": {}, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1b4dac8e-3ad2-46eb-b801-ba717e664b93", + "metadata": {}, + "outputs": [], + "source": [ + "Cpp::LoadLibrary(\"libomp\");" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5001e441-1fa5-4bdc-9fa5-2ca103ae484f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World!\n" + ] + } + ], + "source": [ + "void example1() {\n", + " std::cout << \"Hello World!\" << std::endl;\n", + "}\n", + "example1();" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "53fb7656-b72e-42bc-ade7-2ae2077142da", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World!Hello World!\n", + "Hello World!Hello World!\n", + "Hello World!\n", + "\n", + "Hello World!\n", + "\n", + "Hello World!\n", + "Hello World!\n" + ] + } + ], + "source": [ + "void example2() {\n", + " #pragma omp parallel\n", + " {\n", + " std::cout << \"Hello World!\" << std::endl;\n", + " }\n", + "}\n", + "example2();" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "efcdfdb6-a60b-46af-8194-75ef9cc0e27f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World! (Hello World! (Hello World! (Hello World! (34)\n", + "Hello World! (7)\n", + "0)\n", + "2Hello World! (6))\n", + "\n", + ")\n", + "Hello World! (5)\n", + "Hello World! (1)\n" + ] + } + ], + "source": [ + "void example3() {\n", + " #pragma omp parallel\n", + " {\n", + " std::cout << \"Hello World! (\" << omp_get_thread_num() << \")\" << std::endl;\n", + " }\n", + "}\n", + "example3();" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d86a9efa-ba28-4cb6-bbfc-abc00ee63506", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World! (Hello World! (34))\n", + "Hello World! (0)\n", + "Hello World! (2)\n", + "Hello World! (Hello World! (1)\n", + "\n", + "7)Hello World! (\n", + "6)\n", + "Hello World! (5)\n", + "This is another message! (0)\n", + "Goodbye World! (0)\n", + "Goodbye World! (1)\n" + ] + } + ], + "source": [ + "void example4() {\n", + " #pragma omp parallel\n", + " {\n", + " std::cout << \"Hello World! (\" << omp_get_thread_num() << \")\" << std::endl;\n", + " }\n", + "\n", + " std::cout << \"This is another message! (\" << omp_get_thread_num() << \")\" << std::endl;\n", + "\n", + " #pragma omp parallel num_threads(2)\n", + " {\n", + " std::cout << \"Goodbye World! (\" << omp_get_thread_num() << \")\" << std::endl;\n", + " }\n", + "}\n", + "example4();" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "5557e01a-7c7d-4b54-8545-962ad11027df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initialize a[] time: 0.588681\n", + "Initialize b[] time: 0.513927\n", + "Add arrays time: 1.58928\n", + "Average result time: 0.637053\n", + "Average: 5e+08\n", + "Total time: 3.33191\n" + ] + } + ], + "source": [ + "void example5() {\n", + " double start_time = omp_get_wtime();\n", + " double start_loop;\n", + " \n", + " const int N = 1000000000;\n", + " int* a = new int[N];\n", + " int* b = new int[N];\n", + " \n", + " start_loop = omp_get_wtime();\n", + " #pragma omp parallel for\n", + " for (int i=0; i\n", + "#include \n", + "#include " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "93b89565-44fe-4729-980b-d4f897161b0b", + "metadata": {}, + "outputs": [], + "source": [ + "Cpp::LoadLibrary(\"libomp\");" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9078ac79-ca50-4fef-b785-37f35fec3cab", + "metadata": {}, + "outputs": [], + "source": [ + "static long num_steps = 100000000;\n", + "double step;" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f3c10995-6f29-4d71-9e61-1993ca9d1cc9", + "metadata": {}, + "outputs": [], + "source": [ + "int main() {\n", + " int i, j, num_threads_allocated;\n", + " double x, pi, sum = 0.0;\n", + " double start_time, run_time;\n", + "\n", + " step = 1.0 / (double)num_steps;\n", + " printf(\"Num threads available: %d\\n\", omp_get_max_threads());\n", + " for (i = 1; i <= 4; i++) {\n", + " sum = 0.0;\n", + " omp_set_num_threads(i);\n", + " start_time = omp_get_wtime();\n", + "#pragma omp parallel\n", + " {\n", + " num_threads_allocated = omp_get_num_threads();\n", + "#pragma omp single\n", + " printf(\"Num threads allocated for this run: %d\\n\", num_threads_allocated);\n", + "\n", + "#pragma omp for reduction(+ : sum)\n", + " for (j = 1; j <= num_steps; j++) {\n", + " x = (j - 0.5) * step;\n", + " sum = sum + 4.0 / (1.0 + x * x);\n", + " }\n", + " }\n", + "\n", + " pi = step * sum;\n", + " run_time = omp_get_wtime() - start_time;\n", + " printf(\"pi is %f in %f seconds using %d threads\\n\\n\", pi, run_time, num_threads_allocated);\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "0f84442a-d947-4860-bd3c-aeeea963b419", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Num threads available: 8\n", + "Num threads allocated for this run: 1\n", + "pi is 3.141593 in 0.179501 seconds using 1 threads\n", + "\n", + "Num threads allocated for this run: 2\n", + "pi is 3.141592 in 0.184605 seconds using 2 threads\n", + "\n", + "Num threads allocated for this run: 3\n", + "pi is 3.141593 in 0.097145 seconds using 3 threads\n", + "\n", + "Num threads allocated for this run: 4\n", + "pi is 3.141593 in 0.071473 seconds using 4 threads\n", + "\n" + ] + } + ], + "source": [ + "main();" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "C++17 (xcpp+OpenMP)", + "language": "cpp", + "name": "xcpp17-omp" + }, + "language_info": { + "codemirror_mode": "text/x-c++src", + "file_extension": ".cpp", + "mimetype": "text/x-c++src", + "name": "C++", + "version": "17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/share/jupyter/kernels/xc11-omp/kernel.json.in b/share/jupyter/kernels/xc11-omp/kernel.json.in new file mode 100644 index 00000000..fc5dbbbd --- /dev/null +++ b/share/jupyter/kernels/xc11-omp/kernel.json.in @@ -0,0 +1,18 @@ +{ + "display_name": "C11 + OpenMP", + "env": { + "PATH":"@XEUS_CPP_PATH@", + "LD_LIBRARY_PATH":"@OpenMPLibraryDir@" + }, + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-f", + "{connection_file}", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@","-xc", + "-I", "@XEUS_CPP_INCLUDE_DIR@", + "-std=c11","@XEUS_CPP_OMP@" + ], + "language": "c", + "metadata": {"debugger": false + } +} diff --git a/share/jupyter/kernels/xc11-omp/logo-32x32.png b/share/jupyter/kernels/xc11-omp/logo-32x32.png new file mode 100644 index 00000000..18f36dff Binary files /dev/null and b/share/jupyter/kernels/xc11-omp/logo-32x32.png differ diff --git a/share/jupyter/kernels/xc11-omp/logo-64x64.png b/share/jupyter/kernels/xc11-omp/logo-64x64.png new file mode 100644 index 00000000..249b3cb2 Binary files /dev/null and b/share/jupyter/kernels/xc11-omp/logo-64x64.png differ diff --git a/share/jupyter/kernels/xc11-omp/logo-svg.svg b/share/jupyter/kernels/xc11-omp/logo-svg.svg new file mode 100644 index 00000000..6c15fbc2 --- /dev/null +++ b/share/jupyter/kernels/xc11-omp/logo-svg.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + diff --git a/share/jupyter/kernels/xc17-omp/kernel.json.in b/share/jupyter/kernels/xc17-omp/kernel.json.in new file mode 100644 index 00000000..44676999 --- /dev/null +++ b/share/jupyter/kernels/xc17-omp/kernel.json.in @@ -0,0 +1,18 @@ +{ + "display_name": "C17 + OpenMP", + "env": { + "PATH":"@XEUS_CPP_PATH@", + "LD_LIBRARY_PATH":"@OpenMPLibraryDir@" + }, + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-f", + "{connection_file}", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@","-xc", + "-I", "@XEUS_CPP_INCLUDE_DIR@", + "-std=c17","@XEUS_CPP_OMP@" + ], + "language": "c", + "metadata": {"debugger": false + } +} diff --git a/share/jupyter/kernels/xc17-omp/logo-32x32.png b/share/jupyter/kernels/xc17-omp/logo-32x32.png new file mode 100644 index 00000000..18f36dff Binary files /dev/null and b/share/jupyter/kernels/xc17-omp/logo-32x32.png differ diff --git a/share/jupyter/kernels/xc17-omp/logo-64x64.png b/share/jupyter/kernels/xc17-omp/logo-64x64.png new file mode 100644 index 00000000..249b3cb2 Binary files /dev/null and b/share/jupyter/kernels/xc17-omp/logo-64x64.png differ diff --git a/share/jupyter/kernels/xc17-omp/logo-svg.svg b/share/jupyter/kernels/xc17-omp/logo-svg.svg new file mode 100644 index 00000000..6c15fbc2 --- /dev/null +++ b/share/jupyter/kernels/xc17-omp/logo-svg.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + diff --git a/share/jupyter/kernels/xc23-omp/kernel.json.in b/share/jupyter/kernels/xc23-omp/kernel.json.in new file mode 100644 index 00000000..9e7b0a7a --- /dev/null +++ b/share/jupyter/kernels/xc23-omp/kernel.json.in @@ -0,0 +1,18 @@ +{ + "display_name": "C23 + OpenMP", + "env": { + "PATH":"@XEUS_CPP_PATH@", + "LD_LIBRARY_PATH":"@OpenMPLibraryDir@" + }, + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-f", + "{connection_file}", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@","-xc", + "-I", "@XEUS_CPP_INCLUDE_DIR@", + "-std=c23","@XEUS_CPP_OMP@" + ], + "language": "c", + "metadata": {"debugger": false + } +} diff --git a/share/jupyter/kernels/xc23-omp/logo-32x32.png b/share/jupyter/kernels/xc23-omp/logo-32x32.png new file mode 100644 index 00000000..18f36dff Binary files /dev/null and b/share/jupyter/kernels/xc23-omp/logo-32x32.png differ diff --git a/share/jupyter/kernels/xc23-omp/logo-64x64.png b/share/jupyter/kernels/xc23-omp/logo-64x64.png new file mode 100644 index 00000000..249b3cb2 Binary files /dev/null and b/share/jupyter/kernels/xc23-omp/logo-64x64.png differ diff --git a/share/jupyter/kernels/xc23-omp/logo-svg.svg b/share/jupyter/kernels/xc23-omp/logo-svg.svg new file mode 100644 index 00000000..6c15fbc2 --- /dev/null +++ b/share/jupyter/kernels/xc23-omp/logo-svg.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + diff --git a/share/jupyter/kernels/xcpp17-omp/kernel.json.in b/share/jupyter/kernels/xcpp17-omp/kernel.json.in index f74379f1..6ffc8423 100644 --- a/share/jupyter/kernels/xcpp17-omp/kernel.json.in +++ b/share/jupyter/kernels/xcpp17-omp/kernel.json.in @@ -1,8 +1,8 @@ { - "display_name": "C++17 (xcpp+OpenMP)", + "display_name": "C++17 + OpenMP", "env": { "PATH":"@XEUS_CPP_PATH@", - "LD_LIBRARY_PATH":"@XEUS_CPP_LD_LIBRARY_PATH@" + "LD_LIBRARY_PATH":"@OpenMPLibraryDir@" }, "argv": [ "@XEUS_CPP_KERNELSPEC_PATH@xcpp", @@ -10,7 +10,7 @@ "{connection_file}", "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@", "-I", "@XEUS_CPP_INCLUDE_DIR@", - "-std=c++17"@XEUS_CPP_OMP@ + "-std=c++17","@XEUS_CPP_OMP@" ], "language": "cpp", "metadata": {"debugger": false diff --git a/share/jupyter/kernels/xcpp20-omp/kernel.json.in b/share/jupyter/kernels/xcpp20-omp/kernel.json.in new file mode 100644 index 00000000..f9546231 --- /dev/null +++ b/share/jupyter/kernels/xcpp20-omp/kernel.json.in @@ -0,0 +1,18 @@ +{ + "display_name": "C++20 + OpenMP", + "env": { + "PATH":"@XEUS_CPP_PATH@", + "LD_LIBRARY_PATH":"@OpenMPLibraryDir@" + }, + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-f", + "{connection_file}", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@", + "-I", "@XEUS_CPP_INCLUDE_DIR@", + "-std=c++20","@XEUS_CPP_OMP@" + ], + "language": "cpp", + "metadata": {"debugger": false + } +} diff --git a/share/jupyter/kernels/xcpp20-omp/logo-32x32.png b/share/jupyter/kernels/xcpp20-omp/logo-32x32.png new file mode 100644 index 00000000..c09c4585 Binary files /dev/null and b/share/jupyter/kernels/xcpp20-omp/logo-32x32.png differ diff --git a/share/jupyter/kernels/xcpp20-omp/logo-64x64.png b/share/jupyter/kernels/xcpp20-omp/logo-64x64.png new file mode 100644 index 00000000..396c2446 Binary files /dev/null and b/share/jupyter/kernels/xcpp20-omp/logo-64x64.png differ diff --git a/share/jupyter/kernels/xcpp20-omp/logo-svg.svg b/share/jupyter/kernels/xcpp20-omp/logo-svg.svg new file mode 100644 index 00000000..5e117077 --- /dev/null +++ b/share/jupyter/kernels/xcpp20-omp/logo-svg.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + diff --git a/share/jupyter/kernels/xcpp23-omp/kernel.json.in b/share/jupyter/kernels/xcpp23-omp/kernel.json.in new file mode 100644 index 00000000..abcdf6cc --- /dev/null +++ b/share/jupyter/kernels/xcpp23-omp/kernel.json.in @@ -0,0 +1,18 @@ +{ + "display_name": "C++23 + OpenMP", + "env": { + "PATH":"@XEUS_CPP_PATH@", + "LD_LIBRARY_PATH":"@OpenMPLibraryDir@" + }, + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-f", + "{connection_file}", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@", + "-I", "@XEUS_CPP_INCLUDE_DIR@", + "-std=c++23","@XEUS_CPP_OMP@" + ], + "language": "cpp", + "metadata": {"debugger": false + } +} diff --git a/share/jupyter/kernels/xcpp23-omp/logo-32x32.png b/share/jupyter/kernels/xcpp23-omp/logo-32x32.png new file mode 100644 index 00000000..c09c4585 Binary files /dev/null and b/share/jupyter/kernels/xcpp23-omp/logo-32x32.png differ diff --git a/share/jupyter/kernels/xcpp23-omp/logo-64x64.png b/share/jupyter/kernels/xcpp23-omp/logo-64x64.png new file mode 100644 index 00000000..396c2446 Binary files /dev/null and b/share/jupyter/kernels/xcpp23-omp/logo-64x64.png differ diff --git a/share/jupyter/kernels/xcpp23-omp/logo-svg.svg b/share/jupyter/kernels/xcpp23-omp/logo-svg.svg new file mode 100644 index 00000000..5e117077 --- /dev/null +++ b/share/jupyter/kernels/xcpp23-omp/logo-svg.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + diff --git a/test/test_xcpp_kernel.py b/test/test_xcpp_kernel.py index 69a9e69e..2c0e88f5 100644 --- a/test/test_xcpp_kernel.py +++ b/test/test_xcpp_kernel.py @@ -63,7 +63,7 @@ def test_continuation(self) -> None: self.assertEqual(str(reply["content"]["indent"]), "") self.assertEqual(reply["content"]["status"], "complete") -kernel_names = ['xcpp17', 'xcpp20', 'xcpp23'] +kernel_names = ['xcpp17', 'xcpp20', 'xcpp23','xcpp17-omp', 'xcpp20-omp', 'xcpp23-omp'] for name in kernel_names: class_name = f"XCppCompleteTests_{name}" @@ -225,5 +225,60 @@ class BaseXCppTests2(jupyter_kernel_test.KernelTests): } ) +if platform.system() != 'Windows': + class BaseXCppOpenMPTests(jupyter_kernel_test.KernelTests): + __test__ = False + + # language_info.name in a kernel_info_reply should match this + language_name = 'C++' + + # OpenMP test that creates 2 threads, and gets them to output their thread + # number in descending order + code_omp=""" + #include + #include + #include + Cpp::LoadLibrary("libomp"); + """ + + code_omp_2=""" + int main() { + omp_set_num_threads(2); + #pragma omp parallel + { + if (omp_get_thread_num() == 1) { + printf("1"); + #pragma omp barrier + } + else if (omp_get_thread_num() == 0) { + #pragma omp barrier + printf("0"); + } + } + } + main(); + """ + + def test_xcpp_omp(self): + self.flush_channels() + reply, output_msgs = self.execute_helper(code=self.code_omp,timeout=20) + reply, output_msgs = self.execute_helper(code=self.code_omp_2,timeout=20) + self.assertEqual(output_msgs[0]['msg_type'], 'stream') + self.assertEqual(output_msgs[0]['content']['name'], 'stdout') + self.assertEqual(output_msgs[0]['content']['text'], '10') + + kernel_names = ['xcpp17-omp', 'xcpp20-omp', 'xcpp23-omp'] + + for name in kernel_names: + class_name = f"XCppOpenMPTests_{name}" + globals()[class_name] = type( + class_name, + (BaseXCppOpenMPTests,), + { + 'kernel_name': name, + '__test__': True + } + ) + if __name__ == '__main__': unittest.main()