upload exercises
27
Exercise2c/OUTDATED_process_image.py
Executable file
|
@ -0,0 +1,27 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
# This module provides the magic_signature() function, safely and
|
||||
# securely calculated to provide invaluable signature of an image.
|
||||
|
||||
def magic(fname):
|
||||
n_threads = os.getenv('OMP_NUM_THREADS', '(unset)')
|
||||
print(f"Worker {fname=} OMP_NUM_THREADS={n_threads}")
|
||||
|
||||
# We delay the import of numpy because we want to set OMP_NUM_THREADS.
|
||||
# We delay the import of PIL in case is uses numpy internally.
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
im = Image.open(fname)
|
||||
try:
|
||||
m = np.median(im, axis=2)
|
||||
except np.AxisError:
|
||||
return -1
|
||||
n = (m @ m.T).mean()
|
||||
return int(n)
|
||||
|
||||
if __name__ == '__main__':
|
||||
for fname in sys.argv[1:]:
|
||||
print(f'{fname} → {magic(fname)}')
|
35
Exercise2c/OUTDATED_process_many_times.py
Executable file
|
@ -0,0 +1,35 @@
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from process_multiple_images import process
|
||||
|
||||
n_threads = ...
|
||||
n_processes = ...
|
||||
|
||||
def measure_one(n_processes, n_threads, fnames):
|
||||
result_fname = f'{n_processes:02}_{n_threads:02}.txt'
|
||||
|
||||
if os.path.exists(result_fname):
|
||||
print(f'Skipping job with {n_processes} processes and {n_threads} threads, results file exists')
|
||||
return
|
||||
|
||||
t0 = time.time()
|
||||
process(n_processes, n_threads, fnames)
|
||||
dt = time.time() - t0
|
||||
|
||||
print(f'Job with {n_processes} processes and {n_threads} threads/worker and {len(fnames)} jobs: {dt}')
|
||||
|
||||
with open(result_fname, 'wt') as results:
|
||||
print(f'{n_processes:02} {n_threads:02} {dt}', file=results)
|
||||
|
||||
def measure(n_processes, n_threads, fnames):
|
||||
for n1 in n_processes:
|
||||
for n2 in n_threads:
|
||||
measure_one(n1, n2, fnames)
|
||||
|
||||
if __name__ == '__main__':
|
||||
measure(
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||
sys.argv[1:])
|
25
Exercise2c/OUTDATED_process_multiple_images.py
Executable file
|
@ -0,0 +1,25 @@
|
|||
import os
|
||||
import sys
|
||||
from multiprocessing import Pool as ProcessPool
|
||||
|
||||
import process_image
|
||||
|
||||
def process(n_processes, n_threads, fnames):
|
||||
print(f"Controller with {n_processes} processes and {n_threads} threads / worker")
|
||||
|
||||
# The environment that is set in the parent is inherited by child workers,
|
||||
# but here process_image import numpy, so we need to set the variable
|
||||
# before process_image is imported.
|
||||
os.environ['OMP_NUM_THREADS'] = str(n_threads)
|
||||
|
||||
with ProcessPool(n_processes) as p:
|
||||
signatures = p.map(process_image.magic, fnames)
|
||||
for fname, signature in zip(fnames, signatures):
|
||||
print(f'{fname} → {signature}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
n_processes = int(sys.argv[1])
|
||||
n_threads = int(sys.argv[2])
|
||||
fnames = sys.argv[3:]
|
||||
|
||||
process(n_processes, n_threads, fnames)
|
20
Exercise2c/README.md
Executable file
|
@ -0,0 +1,20 @@
|
|||
## Exercise 2c
|
||||
|
||||
Processing images with simultaneous multiprocessing and multithreading.
|
||||
|
||||
`process_image.py` processes a single image.
|
||||
It can be used as a script: `process_image.py foo.jpg`
|
||||
It is also an importable module. `process_image.magic("foo.jpg")`
|
||||
|
||||
`process_multiple_images` uses `process_image` to process a series of images.
|
||||
It should be called as following:
|
||||
`process_multiple_images n_processes n_threads filename1.png filename2.png …`
|
||||
|
||||
1. start a separate terminal window with `htop`: `gnome-terminal -- htop &`
|
||||
|
||||
2. call `python process_multiple_images.py 2 2 images/*.png`
|
||||
|
||||
You should see `htop` showing 4 threads (2 worked processes × 2 numpy threads).
|
||||
|
||||
Play with different numbers of processes and threads.
|
||||
Which combination is optimum (fastest)?
|
BIN
Exercise2c/processed_images/f32.png
Executable file
After Width: | Height: | Size: 422 KiB |
BIN
Exercise2c/processed_images/f33-01-dawn.png
Executable file
After Width: | Height: | Size: 289 KiB |
BIN
Exercise2c/processed_images/f33-02-day.png
Executable file
After Width: | Height: | Size: 280 KiB |
BIN
Exercise2c/processed_images/f33-03-dusk.png
Executable file
After Width: | Height: | Size: 246 KiB |
BIN
Exercise2c/processed_images/f33-04-night.png
Executable file
After Width: | Height: | Size: 262 KiB |
BIN
Exercise2c/processed_images/f33.png
Executable file
After Width: | Height: | Size: 280 KiB |
BIN
Exercise2c/processed_images/f34-01-day.png
Executable file
After Width: | Height: | Size: 493 KiB |
BIN
Exercise2c/processed_images/f34-02-night.png
Executable file
After Width: | Height: | Size: 453 KiB |
BIN
Exercise2c/processed_images/f34.png
Executable file
After Width: | Height: | Size: 493 KiB |
BIN
Exercise2c/processed_images/f35-01-day.png
Executable file
After Width: | Height: | Size: 515 KiB |
BIN
Exercise2c/processed_images/f35-02-night.png
Executable file
After Width: | Height: | Size: 468 KiB |
BIN
Exercise2c/processed_images/f35.png
Executable file
After Width: | Height: | Size: 515 KiB |
BIN
Exercise2c/processed_images/f36-01-day.png
Executable file
After Width: | Height: | Size: 348 KiB |
BIN
Exercise2c/processed_images/f36-02-night.png
Executable file
After Width: | Height: | Size: 357 KiB |
BIN
Exercise2c/processed_images/f36.png
Executable file
After Width: | Height: | Size: 348 KiB |
BIN
Exercise2c/processed_images/f37-01-day.png
Executable file
After Width: | Height: | Size: 222 KiB |
BIN
Exercise2c/processed_images/f37-01-night.png
Executable file
After Width: | Height: | Size: 221 KiB |
BIN
Exercise2c/processed_images/f38-01-day.png
Executable file
After Width: | Height: | Size: 666 KiB |
BIN
Exercise2c/processed_images/f38-01-night.png
Executable file
After Width: | Height: | Size: 607 KiB |