diff --git a/examples/slurm/README.md b/examples/slurm/README.md index a4cb306db2ab7989795257a811b2406793584cd7..7dc183fdca755be3fd19f3fc65dfb4f5aed08b2f 100644 --- a/examples/slurm/README.md +++ b/examples/slurm/README.md @@ -1,7 +1,18 @@ -Examples for Python submit scripts for MPCDF HPC systems: +# Examples for Python Slurm scripts for MPCDF HPC systems + +## Small programs and problem sizes * sequential program + +## Full-node setups for larger problems + * multithreaded program using NumPy/MKL * parallel program using Python's multiprocessing (restricted to a single node) * parallel program using MPI for Python (mpi4py, multi-node) +Important: Before using full nodes, please check that your program actually +benefits from these powerful resources, otherwise use shared nodes. + +Find up-to-date documentation on Slurm and related topics at: +https://docs.mpcdf.mpg.de/doc/computing/index.html + diff --git a/examples/slurm/python_multiprocessing.py b/examples/slurm/python_multiprocessing.py index eef585af93b36da8022acddf845c91f67b109b6f..0685961df47a3b5bdb2a65acb8f517baf025888f 100755 --- a/examples/slurm/python_multiprocessing.py +++ b/examples/slurm/python_multiprocessing.py @@ -9,8 +9,10 @@ def my_f(x): print("{} : {}".format(x, os.getpid())) # set the number of processes to be used -#np = mp.cpu_count() # ... as detected by multiprocessing -np = int(sys.argv[1]) # ... as passed in via the command line +try: + np = int(sys.argv[1]) # ... as passed in via the command line, if possible +except: + np = mp.cpu_count() # ... else as detected by multiprocessing with mp.Pool(np) as p: p.map(my_f, range(np)) diff --git a/examples/slurm/python_multithreading.py b/examples/slurm/python_multithreading.py index 1ec5c68f9367c5ce2e76e9fd8c6ca03a103f5208..d32ef34f83c25c139d33c8451fc353890fc12ec0 100755 --- a/examples/slurm/python_multithreading.py +++ b/examples/slurm/python_multithreading.py @@ -5,7 +5,8 @@ import numpy as np n = 4096 M = np.random.rand(n, n) -# the following call may use threading +# The following call may use multi-threading using the underlying +# high-performance math libraries NumPy is linked to (e.g. MKL): N = np.matmul(M, M) print(N.size) diff --git a/examples/slurm/submit_mpi4py.sh b/examples/slurm/submit_mpi4py.sh index 54077b8b2c2775328a6d7631f19f76fde99efa97..d789d21cb94a963868969cd61aa9ac8992d19d20 100644 --- a/examples/slurm/submit_mpi4py.sh +++ b/examples/slurm/submit_mpi4py.sh @@ -1,22 +1,24 @@ #!/bin/bash -l - +# +# Example job script for using MPI4PY on Cobra@MPCDF. +# #SBATCH -o ./job.out.%j #SBATCH -e ./job.err.%j #SBATCH -D ./ #SBATCH -J PYTHON_MPI #SBATCH --mail-type=none -###SBATCH --partition=general # note: general partition is necessary on DRACO for jobs with >1 nodes, not on COBRA #SBATCH --nodes=1 -#SBATCH --ntasks-per-node=32 +#SBATCH --ntasks-per-node=40 #SBATCH --cpus-per-task=1 -#SBATCH --time=00:01:00 # run time in h:m:s, up to 24h possible +#SBATCH --time=00:10:00 # run time in h:m:s, up to 24h possible module purge -module load gcc/10 impi/2019.8 -module load anaconda/3/2019.03 -module load mpi4py +module load gcc/10 impi/2019.9 +module load anaconda/3/2021.05 +module load mpi4py/3.0.3 -# avoid overbooking of the cores which might occur via NumPy/MKL threading +# avoid overbooking of the cores which would occur via NumPy/MKL threading +# as the parallelization takes place via MPI tasks export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK:-1} srun python ./python_mpi4py.py diff --git a/examples/slurm/submit_multiprocessing.sh b/examples/slurm/submit_multiprocessing.sh index 2316c0518fcd53701d021db9e43b672784dd187b..c1f112c865c70ef0d1feac982f44fd61dc74d0d8 100644 --- a/examples/slurm/submit_multiprocessing.sh +++ b/examples/slurm/submit_multiprocessing.sh @@ -1,5 +1,7 @@ #!/bin/bash -l - +# +# Example job script for using Python-Multiprocessing on Cobra@MPCDF. +# #SBATCH -o ./job.out.%j #SBATCH -e ./job.err.%j #SBATCH -D ./ @@ -7,14 +9,17 @@ #SBATCH --mail-type=none #SBATCH --nodes=1 #SBATCH --ntasks-per-node=1 # only start 1 task via srun because Python multiprocessing starts more tasks internally -#SBATCH --cpus-per-task=32 # assign all the cores to that first task to make room for Python's multiprocessing tasks -#SBATCH --time=00:01:00 +#SBATCH --cpus-per-task=40 # assign all the cores to that first task to make room for Python's multiprocessing tasks +#SBATCH --time=00:10:00 module purge -module load gcc/10 impi/2019.8 -module load anaconda/3/2019.03 +module load gcc/10 impi/2019.9 +module load anaconda/3/2021.05 -# avoid overbooking of the cores which might occur via NumPy/MKL threading +# avoid overbooking of the cores which might occur via NumPy/MKL threading, +# as the parallelization takes place via processes/multiprocessing export OMP_NUM_THREADS=1 +# pass the number of available cores via the command line, and +# use that number to spawn as many workers from multiprocessing srun python ./python_multiprocessing.py $SLURM_CPUS_PER_TASK diff --git a/examples/slurm/submit_multithreading.sh b/examples/slurm/submit_multithreading.sh index 7cbb5bc989d2d29224a2197ba553cf95b94befa7..dec6259819bc738de180903905e0b1e48a4fd5ad 100644 --- a/examples/slurm/submit_multithreading.sh +++ b/examples/slurm/submit_multithreading.sh @@ -1,19 +1,26 @@ #!/bin/bash -l - +# +# Example job script for using Python with Multithreading (OpenMP, Numba, numexpr) on Cobra@MPCDF. +# #SBATCH -o ./job.out.%j #SBATCH -e ./job.err.%j #SBATCH -D ./ -#SBATCH -J PYTHON_MP +#SBATCH -J PYTHON_MT #SBATCH --mail-type=none #SBATCH --nodes=1 #SBATCH --ntasks-per-node=1 # only start 1 task via srun because Python multiprocessing starts more tasks internally -#SBATCH --cpus-per-task=32 # assign all the cores to that first task to make room for Python's multiprocessing tasks -#SBATCH --time=00:01:00 +#SBATCH --cpus-per-task=40 # assign all the cores to that first task to make room for Python's multiprocessing tasks +#SBATCH --time=00:10:00 module purge -module load gcc/10 impi/2019.8 -module load anaconda/3/2019.03 +module load gcc/10 impi/2019.9 +module load anaconda/3/2021.05 +# set the correct number of threads for various thread-parallel modules export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK +export NUMBA_NUM_THREADS=$SLURM_CPUS_PER_TASK +export NUMEXPR_NUM_THREADS=$SLURM_CPUS_PER_TASK +# pin OpenMP threads to cores +export OMP_PLACES=cores srun python ./python_multithreading.py diff --git a/examples/slurm/submit_sequential.sh b/examples/slurm/submit_sequential.sh index 3d785aa52d773a89e1b5c099180050a2db9efd1c..1c6dd5f7ef72df71c3b4679b73dca95c74bdbdef 100644 --- a/examples/slurm/submit_sequential.sh +++ b/examples/slurm/submit_sequential.sh @@ -1,5 +1,7 @@ #!/bin/bash -l - +# +# Example Slurm job script for a small sequential Python program on MPCDF systems. +# #SBATCH -J PYTHON # job name #SBATCH -o ./job.out.%j # standard out file #SBATCH -e ./job.err.%j # standard err file @@ -7,14 +9,11 @@ #SBATCH --ntasks=1 # launch job on a single core #SBATCH --cpus-per-task=1 # on a shared node #SBATCH --mem=2000MB # memory limit for the job -#SBATCH --time=0:29:59 # run time, up to 24h -# Important: You must use the small partition on DRACO for jobs on a shared node, -# so enable the following line when running on DRACO: -###SBATCH --partition=small +#SBATCH --time=0:10:00 # run time, up to 24h module purge -module load gcc/10 impi/2019.8 -module load anaconda/3/2019.03 +module load gcc/10 impi/2019.9 +module load anaconda/3/2021.05 # avoid overbooking of the cores which might occur via NumPy/MKL threading export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK:-1} diff --git a/exercises/Python_Recap_Exercise.ipynb b/exercises/Python-refresher-Exercise.ipynb similarity index 93% rename from exercises/Python_Recap_Exercise.ipynb rename to exercises/Python-refresher-Exercise.ipynb index 34f0c0e6ec001e5f5a0b5f52a8e614fb7f30307b..df4792b7dc179ad8a6bcd42ccddcab06e112c6c8 100644 --- a/exercises/Python_Recap_Exercise.ipynb +++ b/exercises/Python-refresher-Exercise.ipynb @@ -6,8 +6,9 @@ "source": [ "# Python for HPC\n", "\n", - "## Sebastian Ohlmann, Klaus Reuter\n", - "## Max Planck Computing and Data Facility, Garching" + "### 2018 - 2021 Sebastian Ohlmann, Klaus Reuter\n", + "\n", + "### Max Planck Computing and Data Facility, Garching" ] }, { @@ -29,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -44,7 +45,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +67,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -76,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -88,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -114,7 +115,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -123,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -135,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -145,7 +146,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -163,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -173,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -194,7 +195,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -213,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -246,7 +247,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -259,7 +260,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -277,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -301,7 +302,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -324,14 +325,14 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "pseudo-random word: Florence's\n" + "pseudo-random word: dwindling\n" ] } ], @@ -342,7 +343,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -413,7 +414,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ @@ -425,7 +426,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -478,7 +479,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -495,7 +496,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 27, "metadata": { "scrolled": true }, @@ -539,7 +540,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -556,7 +557,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -598,27 +599,31 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "pi is approximately: 3.142\n", "pi is approximately: 3.142\n" ] } ], "source": [ "import math\n", - "# print pi to three decimals. Use string formatting via '{}'\n", + "# print pi to three decimals. Use string formatting via '{}' and .format()!\n", + "#?\n", + "print(msg)\n", + "# print pi to three decimals. Use string formatting using an f-string!\n", "#?\n", "print(msg)" ] }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -633,7 +638,7 @@ "# Check if the following sentence is a palindrome,\n", "# ignoring capitalization, punctuation, and whitespace.\n", "# Use string methods, see https://docs.python.org/3/library/stdtypes.html#string-methods\n", - "# palindrome credit: https://www2.cs.arizona.edu/icon/oddsends/palinsen.htm\n", + "# Palindrome credit: https://www2.cs.arizona.edu/icon/oddsends/palinsen.htm\n", "pal = \"I saw desserts; I'd no lemons, alas no melon. Distressed was I.\"\n", "#?\n", "#?\n", @@ -652,15 +657,15 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['Advection-withsolution.ipynb', 'Kawai-K5000W-Fret-Noise.wav', 'MPI-solutions', 'Casio-CZ-5000-Synth-Bass-C1.wav', 'Parallel_Exercise_withsolution.ipynb', 'Diffusion_serial_withsolution.ipynb', 'words.txt', 'Diffusion_MPI_withsolution.py', 'Python_Recap_Exercise_withsolution.ipynb', 'NumPy_Exercise_withsolution.ipynb', '.ipynb_checkpoints']\n", - "5\n" + "['Kawai-K5000W-Fret-Noise.wav', 'Diffusion_MPI_withsolution.py', 'Diffusion_serial_withsolution.ipynb', 'Parallel_Exercise_withsolution.ipynb', 'Casio-CZ-5000-Synth-Bass-C1.wav', 'Python_Recap_Exercise_withsolution.ipynb', 'words.txt', 'Software_engineering_Exercise_withsolution.ipynb', 'MPI-solutions', '.ipynb_checkpoints', 'NumPy_Exercise_withsolution.ipynb', 'Advection-withsolution.ipynb']\n", + "6\n" ] } ], @@ -692,7 +697,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -707,7 +712,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 34, "metadata": {}, "outputs": [], "source": [ @@ -719,7 +724,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 35, "metadata": {}, "outputs": [], "source": [ @@ -731,7 +736,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -764,7 +769,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.8.8" } }, "nbformat": 4, diff --git a/exercises/solutions/Advection-withsolution.ipynb b/exercises/_solutions/Advection-withsolution.ipynb similarity index 100% rename from exercises/solutions/Advection-withsolution.ipynb rename to exercises/_solutions/Advection-withsolution.ipynb diff --git a/exercises/_solutions/Casio-CZ-5000-Synth-Bass-C1.wav b/exercises/_solutions/Casio-CZ-5000-Synth-Bass-C1.wav new file mode 120000 index 0000000000000000000000000000000000000000..4370a5011cf8b525a4e79111b78c0e919726f59e --- /dev/null +++ b/exercises/_solutions/Casio-CZ-5000-Synth-Bass-C1.wav @@ -0,0 +1 @@ +../Casio-CZ-5000-Synth-Bass-C1.wav \ No newline at end of file diff --git a/exercises/solutions/Diffusion_MPI_withsolution.py b/exercises/_solutions/Diffusion_MPI_withsolution.py similarity index 100% rename from exercises/solutions/Diffusion_MPI_withsolution.py rename to exercises/_solutions/Diffusion_MPI_withsolution.py diff --git a/exercises/solutions/Diffusion_serial_withsolution.ipynb b/exercises/_solutions/Diffusion_serial_withsolution.ipynb similarity index 100% rename from exercises/solutions/Diffusion_serial_withsolution.ipynb rename to exercises/_solutions/Diffusion_serial_withsolution.ipynb diff --git a/exercises/_solutions/Kawai-K5000W-Fret-Noise.wav b/exercises/_solutions/Kawai-K5000W-Fret-Noise.wav new file mode 120000 index 0000000000000000000000000000000000000000..a7a8ab9b914290c9062eb48f81ed7a78066b0168 --- /dev/null +++ b/exercises/_solutions/Kawai-K5000W-Fret-Noise.wav @@ -0,0 +1 @@ +../Kawai-K5000W-Fret-Noise.wav \ No newline at end of file diff --git a/exercises/solutions/MPI-solutions/block_data_decomposition.py b/exercises/_solutions/MPI-solutions/block_data_decomposition.py similarity index 100% rename from exercises/solutions/MPI-solutions/block_data_decomposition.py rename to exercises/_solutions/MPI-solutions/block_data_decomposition.py diff --git a/exercises/solutions/MPI-solutions/ping-pong.py b/exercises/_solutions/MPI-solutions/ping-pong.py similarity index 100% rename from exercises/solutions/MPI-solutions/ping-pong.py rename to exercises/_solutions/MPI-solutions/ping-pong.py diff --git a/exercises/solutions/MPI-solutions/ring.py b/exercises/_solutions/MPI-solutions/ring.py similarity index 100% rename from exercises/solutions/MPI-solutions/ring.py rename to exercises/_solutions/MPI-solutions/ring.py diff --git a/exercises/solutions/MPI-solutions/scatter_gather.py b/exercises/_solutions/MPI-solutions/scatter_gather.py similarity index 100% rename from exercises/solutions/MPI-solutions/scatter_gather.py rename to exercises/_solutions/MPI-solutions/scatter_gather.py diff --git a/exercises/solutions/MPI-solutions/scatter_reduce.py b/exercises/_solutions/MPI-solutions/scatter_reduce.py similarity index 100% rename from exercises/solutions/MPI-solutions/scatter_reduce.py rename to exercises/_solutions/MPI-solutions/scatter_reduce.py diff --git a/exercises/solutions/NumPy_Exercise_withsolution.ipynb b/exercises/_solutions/NumPy_Exercise_withsolution.ipynb similarity index 100% rename from exercises/solutions/NumPy_Exercise_withsolution.ipynb rename to exercises/_solutions/NumPy_Exercise_withsolution.ipynb diff --git a/exercises/solutions/Parallel_Exercise_withsolution.ipynb b/exercises/_solutions/Parallel_Exercise_withsolution.ipynb similarity index 100% rename from exercises/solutions/Parallel_Exercise_withsolution.ipynb rename to exercises/_solutions/Parallel_Exercise_withsolution.ipynb diff --git a/exercises/solutions/Python_Recap_Exercise_withsolution.ipynb b/exercises/_solutions/Python-refresher-Exercise-with-solution.ipynb similarity index 93% rename from exercises/solutions/Python_Recap_Exercise_withsolution.ipynb rename to exercises/_solutions/Python-refresher-Exercise-with-solution.ipynb index 4cde1fc94eb52f54a8bb50426fe42bfc2eb5c538..a1deb879cc8f2d28126176dedc97c43716056fb1 100644 --- a/exercises/solutions/Python_Recap_Exercise_withsolution.ipynb +++ b/exercises/_solutions/Python-refresher-Exercise-with-solution.ipynb @@ -6,8 +6,9 @@ "source": [ "# Python for HPC\n", "\n", - "## Sebastian Ohlmann, Klaus Reuter\n", - "## Max Planck Computing and Data Facility, Garching" + "### 2018 - 2021 Sebastian Ohlmann, Klaus Reuter\n", + "\n", + "### Max Planck Computing and Data Facility, Garching" ] }, { @@ -29,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -44,7 +45,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +67,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -76,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -88,7 +89,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -114,7 +115,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -123,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -135,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -145,7 +146,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -163,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -173,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -194,7 +195,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -213,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -246,7 +247,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -259,7 +260,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -277,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -301,7 +302,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -324,14 +325,14 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "pseudo-random word: Florence's\n" + "pseudo-random word: dwindling\n" ] } ], @@ -342,7 +343,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -413,7 +414,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ @@ -425,7 +426,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -478,7 +479,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -495,7 +496,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 27, "metadata": { "scrolled": true }, @@ -539,7 +540,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -556,7 +557,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -598,27 +599,31 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "pi is approximately: 3.142\n", "pi is approximately: 3.142\n" ] } ], "source": [ "import math\n", - "# print pi to three decimals. Use string formatting via '{}'\n", + "# print pi to three decimals. Use string formatting via '{}' and .format()!\n", "msg = \"pi is approximately: {:.3f}\".format(math.pi) #$\n", + "print(msg)\n", + "# print pi to three decimals. Use string formatting using an f-string!\n", + "msg = f\"pi is approximately: {math.pi:.3f}\" #$\n", "print(msg)" ] }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -633,7 +638,7 @@ "# Check if the following sentence is a palindrome,\n", "# ignoring capitalization, punctuation, and whitespace.\n", "# Use string methods, see https://docs.python.org/3/library/stdtypes.html#string-methods\n", - "# palindrome credit: https://www2.cs.arizona.edu/icon/oddsends/palinsen.htm\n", + "# Palindrome credit: https://www2.cs.arizona.edu/icon/oddsends/palinsen.htm\n", "pal = \"I saw desserts; I'd no lemons, alas no melon. Distressed was I.\"\n", "pal = pal.lower().replace(';', '').replace('\\'', '').replace(',', '').replace('.', '') #$\n", "print(pal) #$\n", @@ -652,15 +657,15 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['Advection-withsolution.ipynb', 'Kawai-K5000W-Fret-Noise.wav', 'MPI-solutions', 'Casio-CZ-5000-Synth-Bass-C1.wav', 'Parallel_Exercise_withsolution.ipynb', 'Diffusion_serial_withsolution.ipynb', 'words.txt', 'Diffusion_MPI_withsolution.py', 'Python_Recap_Exercise_withsolution.ipynb', 'NumPy_Exercise_withsolution.ipynb', '.ipynb_checkpoints']\n", - "5\n" + "['Kawai-K5000W-Fret-Noise.wav', 'Diffusion_MPI_withsolution.py', 'Diffusion_serial_withsolution.ipynb', 'Parallel_Exercise_withsolution.ipynb', 'Casio-CZ-5000-Synth-Bass-C1.wav', 'Python_Recap_Exercise_withsolution.ipynb', 'words.txt', 'Software_engineering_Exercise_withsolution.ipynb', 'MPI-solutions', '.ipynb_checkpoints', 'NumPy_Exercise_withsolution.ipynb', 'Advection-withsolution.ipynb']\n", + "6\n" ] } ], @@ -692,7 +697,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -707,7 +712,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 34, "metadata": {}, "outputs": [], "source": [ @@ -719,7 +724,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 35, "metadata": {}, "outputs": [], "source": [ @@ -731,7 +736,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -764,7 +769,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.8.8" } }, "nbformat": 4, diff --git a/exercises/solutions/Software_engineering_Exercise_withsolution.ipynb b/exercises/_solutions/Software_engineering_Exercise_withsolution.ipynb similarity index 100% rename from exercises/solutions/Software_engineering_Exercise_withsolution.ipynb rename to exercises/_solutions/Software_engineering_Exercise_withsolution.ipynb diff --git a/exercises/_solutions/words.txt b/exercises/_solutions/words.txt new file mode 120000 index 0000000000000000000000000000000000000000..173e8a551eef0dd10bf9f5d42ae54d3db1d73455 --- /dev/null +++ b/exercises/_solutions/words.txt @@ -0,0 +1 @@ +../words.txt \ No newline at end of file diff --git a/exercises/c_interfacing/README.txt b/exercises/c_interfacing_exercise_readme.txt similarity index 100% rename from exercises/c_interfacing/README.txt rename to exercises/c_interfacing_exercise_readme.txt diff --git a/exercises/solutions/Casio-CZ-5000-Synth-Bass-C1.wav b/exercises/solutions/Casio-CZ-5000-Synth-Bass-C1.wav deleted file mode 120000 index 597152fd989c192846a2bf0319c38b81bb58f6a7..0000000000000000000000000000000000000000 --- a/exercises/solutions/Casio-CZ-5000-Synth-Bass-C1.wav +++ /dev/null @@ -1 +0,0 @@ -../exercises/Casio-CZ-5000-Synth-Bass-C1.wav \ No newline at end of file diff --git a/exercises/solutions/Kawai-K5000W-Fret-Noise.wav b/exercises/solutions/Kawai-K5000W-Fret-Noise.wav deleted file mode 120000 index a2ea1d787bf057ce8219958c0aed9ce95c498618..0000000000000000000000000000000000000000 --- a/exercises/solutions/Kawai-K5000W-Fret-Noise.wav +++ /dev/null @@ -1 +0,0 @@ -../exercises/Kawai-K5000W-Fret-Noise.wav \ No newline at end of file diff --git a/exercises/solutions/words.txt b/exercises/solutions/words.txt deleted file mode 120000 index 0f04af33cc8bd9182fb76ea19ad078ae07470a48..0000000000000000000000000000000000000000 --- a/exercises/solutions/words.txt +++ /dev/null @@ -1 +0,0 @@ -../exercises/words.txt \ No newline at end of file diff --git a/notebooks/2a--NumPy.ipynb b/notebooks/2a--NumPy.ipynb index 97e01fca143cd18a98dac56829da9836095a2132..eca98f9bd570a645506e71b6f975221eb9300139 100644 --- a/notebooks/2a--NumPy.ipynb +++ b/notebooks/2a--NumPy.ipynb @@ -1916,14 +1916,13 @@ }, "outputs": [], "source": [ - "# TODO : needs update because: AttributeError: 'AxesImage' object has no attribute 'filter'\n", - "# from PIL import Image, ImageFilter\n", - "# img = Image.fromarray(ascent().astype(\"int32\"), mode=\"I\").convert(\"L\")\n", - "# filtered_img = im.filter(ImageFilter.FIND_EDGES)\n", + "from PIL import Image, ImageFilter\n", + "img = Image.fromarray(ascent().astype(\"int32\"), mode=\"I\").convert(\"L\")\n", + "filtered_img = img.filter(ImageFilter.FIND_EDGES)\n", "\n", - "# f, axs = plt.subplots(1, 2, figsize=(15, 5))\n", - "# axs[0].imshow(ascent(), cmap='gray')\n", - "# axs[1].imshow(np.asarray(filtered_img), cmap='gray');None" + "f, axs = plt.subplots(1, 2, figsize=(15, 5))\n", + "axs[0].imshow(ascent(), cmap='gray')\n", + "axs[1].imshow(np.asarray(filtered_img), cmap='gray');None" ] }, { @@ -1955,7 +1954,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.8" + "version": "3.8.3" }, "rise": { "enable_chalkboard": true,