Skip to content

Commit 47bed4d

Browse files
authored
Merge pull request #20 from gjbex/development
Add slides on I/O
2 parents fecc51d + 41c4e35 commit 47bed4d

28 files changed

+1645
-3983
lines changed

CODE_OF_CONDUCT.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
layout: page
3+
title: Code of conduct
4+
permalink: /code_of_conduct.html
5+
---
6+
7+
# Code of conduct
8+
9+
This workshop is dedicated to providing a welcoming and supportive environment for all people, regardless of background or identity. By participating in this workshop, participants accept to abide by this Code of Conduct and accept the procedures by which any Code of Conduct incidents are resolved. We do not tolerate behavior that is disrespectful or that excludes, intimidates, or causes discomfort to others. We do not tolerate discrimination or harassment based on characteristics that include, but are not limited to, gender identity and expression, sexual orientation, disability, physical appearance, body size, citizenship, nationality, ethnic or social origin, pregnancy, familial status, veteran status, genetic information, religion or belief (or lack thereof), membership of a national minority, property, age, education, socio-economic status, technical choices, and experience level.
10+
11+
Everyone who participates in workshop activities is required to conform to this Code of Conduct. It applies to all spaces managed by or affiliated with the workshop, including, but not limited to, workshops, email lists, and online forums such as GitHub, Slack and Twitter. Workshop hosts are expected to assist with the enforcement of the Code of Conduct. By participating, participants indicate their acceptance of the procedures by which the workshop resolves any Code of Conduct incidents, which may include storage and processing of their personal information.
12+
13+
14+
## Expected behavior
15+
16+
All participants in our events and communications are expected to show respect and courtesy to others. All interactions should be professional regardless of platform: either online or in-person. In order to foster a positive and professional learning environment we encourage the following kinds of behaviors in all workshop events and platforms:
17+
18+
* Use welcoming and inclusive language
19+
* Be respectful of different viewpoints and experiences
20+
* Gracefully accept constructive criticism
21+
* Focus on what is best for the community
22+
* Show courtesy and respect towards other community members
23+
24+
25+
## Unacceptable behavior
26+
27+
Examples of unacceptable behavior by participants at any workshop event/platform include:
28+
29+
* written or verbal comments which have the effect of excluding people on the basis of membership of any specific group
30+
* causing someone to fear for their safety, such as through stalking, following, or intimidation
31+
* violent threats or language directed against another person
32+
* the display of sexual or violent images
33+
* unwelcome sexual attention
34+
* nonconsensual or unwelcome physical contact
35+
* sustained disruption of talks, events or communications
36+
* insults or put downs
37+
* sexist, racist, homophobic, transphobic, ableist, or exclusionary jokes
38+
* excessive swearing
39+
* incitement to violence, suicide, or self-harm
40+
* continuing to initiate interaction (including photography or recording) with someone after being asked to stop
41+
* publication of private communication without consent
42+
* sharing recordings of training sessions with non-participants
43+
44+
45+
## Consequences of Unacceptable behavior
46+
47+
If you believe someone is violating the Code of Conduct, we ask that you report it to any of the workshop organizers. This is a community-led workshop, and we value the involvement of everyone in the community. We are committed to creating a friendly and respectful place for learning, teaching and contributing. All participants in our events and communications are expected to show respect and courtesy to others.
48+
49+
To make clear what is expected, everyone participating in this conference and its activities is required to conform to the Code of Conduct. This Code of Conduct applies to all spaces affiliated with the conference, but not limited to, workshops, email lists, and online forums such as GitHub, Slack and Twitter. Workshop organizers are expected to assist with the enforcement of the Code of Conduct.
50+
51+
Participants who are asked to stop any inappropriate behavior are expected to comply immediately. This applies to any workshop events and platforms, either online or in-person. If a participant engages in behavior that violates this code of conduct, the organizers may warn the offender, ask them to leave the event or platform, or investigate the Code of Conduct violation and impose appropriate sanctions.
52+
53+
54+
## Attribution
55+
56+
This code of conduct is largely mirrored from the one used by [ML4Science](https://www.ml4science.org/code-of-conduct) that in turn modelled it on the [Software Carpentry's code of conduct](https://www.google.com/url?q=https%3A%2F%2Fdocs.carpentries.org%2Ftopic_folders%2Fpolicies%2Fcode-of-conduct.html&sa=D&sntz=1&usg=AOvVaw3u6XY-Uib9k9m6Y7uxovay).

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ GitHub repository for participants of the "Python for HPC" training.
44
For information on the training, see the website
55
[https://gjbex.github.io/Python-for-HPC/](https://gjbex.github.io/Python-for-HPC/)
66

7+
Note that material for a training on using GPUs in Python is in
8+
[another repository](https://github.com/gjbex/Python-on-GPUs).
9+
710

811
## What is it?
912

@@ -15,3 +18,5 @@ For information on the training, see the website
1518
1. [Contributing](CONTRIBUTING.md): information on how to contribute to this
1619
repository.
1720
1. docs: directory containing the website for this repository.
21+
1. [Code of conduct](CODE_OF_CONDUCT.md): when participating in this training
22+
you accept to abide by the code of conduct.

python_for_hpc.pptx

45.3 KB
Binary file not shown.

source-code/README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ to create it. There is some material not covered in the presentation as well.
1010
* Packages (names listed taht can be used with `pip` or `conda` to install):
1111
* cython
1212
* dask
13+
* numba
1314
* numpy
1415
* numexpr
1516
* scipy
@@ -19,10 +20,6 @@ to create it. There is some material not covered in the presentation as well.
1920
* jupyter
2021
* ipywidgets
2122

22-
* For the GPU code:
23-
* pycuda
24-
* scikit-cuda
25-
2623

2724
## What is it?
2825

@@ -43,5 +40,8 @@ to create it. There is some material not covered in the presentation as well.
4340
1. `numpy-scipy`: some numpy/scipy codes for benchmakring.
4441
1. `pypy`: code to experiment with the Pypy interpreter.
4542
1. `file-formats`: influcence of file formats on performance.
46-
1. `gpu`: some examples of using GPUs.
4743
1. `performance`: general considerations about performance.
44+
1. `convolution`: wrap up exercise to apply all techniques.
45+
46+
**Note:** the GPU code in this repository was moved to
47+
[its own repository](https://github.com/gjbex/Python-on-GPUs)

source-code/convolution/README.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Convolution
2+
3+
Convolution of an image using a kernel makes a nice problem to implement
4+
using various HPC technologies. It is conceptually simple enough to be used
5+
as an exercise, yet computationally sufficiently challenging to make it
6+
interesting.
7+
8+
To get you started, you get a
9+
* [Python](python) implementations, and
10+
* [C++](cpp) implementation.
11+
12+
13+
You can try to:
14+
15+
* use numba,
16+
* use Cython,
17+
* use Swig to bind the C++ implementation,
18+
* use PyBind11 to bind the C++ implementation,
19+
* parallelize the code using Cython,
20+
* parallelize the code using multiprocessing,
21+
* parallelize and run the application on multiple nodes MPI.
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cmake_minimum_required(VERSION 3.18)
2+
project(algorithms LANGUAGES CXX)
3+
4+
set(CMAKE_CXX_STANDARD 23)
5+
set(CMaKE_CXX_STANDARD_REQUIRED YES)
6+
set(CMAKE_CXX_EXTENSIONS NO)
7+
8+
add_compile_options(-Wall -Wextra -Wpedantic)
9+
10+
add_subdirectory(src)

source-code/convolution/cpp/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# C++ implementation
2+
3+
This is a (pretty naive) C++ implementation of 2D convolution.
4+
5+
6+
## What is it?
7+
8+
1. `src/convolution/convolution.h`: declaration of the convolution function.
9+
1. `src/convolution/convolution.cpp`: definition of the convolution function.
10+
1. `src/benchmark_convolution.cpp`: a C++ application to benchmark the
11+
implementation.
12+
1. `src/test_convolution.cpp`: a C++ application to test the implementation.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
add_subdirectory(convolution)
2+
3+
add_executable(test_convolution.exe
4+
test_convolution.cpp)
5+
target_include_directories(test_convolution.exe
6+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/convolution)
7+
target_link_libraries(test_convolution.exe
8+
PRIVATE convolution)
9+
10+
add_executable(benchmark_convolution.exe
11+
benchmark_convolution.cpp)
12+
target_include_directories(benchmark_convolution.exe
13+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/convolution)
14+
target_link_libraries(benchmark_convolution.exe
15+
PRIVATE convolution)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <convolution.h>
2+
#include <chrono>
3+
#include <iostream>
4+
#include <numeric>
5+
#include <random>
6+
7+
Matrix create_image(int rows, int cols) {
8+
std::mt19937 gen(1234);
9+
std::uniform_real_distribution<double> dis(0.0, 1.0);
10+
Matrix image(rows, cols);
11+
for (int i = 0; i < rows; ++i) {
12+
for (int j = 0; j < cols; ++j) {
13+
image(i, j) = dis(gen);
14+
}
15+
}
16+
return image;
17+
}
18+
19+
Matrix create_kernel(int rows, int cols) {
20+
Matrix kernel(rows, cols);
21+
for (int i = 0; i < rows; ++i) {
22+
for (int j = 0; j < cols; ++j) {
23+
kernel(i, j) = 1.0/(rows*cols);
24+
}
25+
}
26+
return kernel;
27+
}
28+
29+
double element_sum(const Matrix& matrix) {
30+
return std::accumulate(matrix.data(), matrix.data() + matrix.rows()*matrix.cols(), 0.0);
31+
}
32+
33+
int main(int argc, char** argv) {
34+
int rows = 1000;
35+
int cols = 1000;
36+
int kernel_rows = 7;
37+
int kernel_cols = 7;
38+
if (argc > 1) {
39+
rows = atoi(argv[1]);
40+
cols = atoi(argv[1]);
41+
}
42+
if (argc > 2) {
43+
kernel_rows = atoi(argv[2]);
44+
kernel_cols = atoi(argv[2]);
45+
}
46+
std::cout << "Image size: " << rows << "x" << cols << "\n";
47+
std::cout << "Kernel size: " << kernel_rows << "x" << kernel_cols << "\n";
48+
Matrix image = create_image(rows, cols);
49+
Matrix kernel = create_kernel(kernel_rows, kernel_cols);
50+
auto start = std::chrono::high_resolution_clock::now();
51+
auto result = convolve(image, kernel);
52+
auto end = std::chrono::high_resolution_clock::now();
53+
std::chrono::duration<double> diff = end - start;
54+
std::cout << "Time: " << diff.count() << " s\n";
55+
std::cout << "Sum: " << element_sum(result) << "\n";
56+
return 0;
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
add_library(convolution SHARED
2+
convolution.cpp matrices.cpp)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "convolution.h"
2+
#include <exception>
3+
4+
Matrix convolve(const Matrix& image, const Matrix& kernel) {
5+
if (kernel.rows() % 2 != 1 || kernel.cols() % 2 != 1) {
6+
throw std::invalid_argument("Only odd dimensions on kernel supported");
7+
}
8+
/*
9+
s_mid and t_mid are number of pixels between the center pixel
10+
and the edge, ie for a 5x5 filter they will be 2.
11+
12+
The output size is calculated by adding s_mid, t_mid to each
13+
side of the dimensions of the input image.
14+
*/
15+
auto s_mid {kernel.rows()/2};
16+
auto t_mid {kernel.cols()/2};
17+
auto x_max {image.rows() + 2*s_mid};
18+
auto y_max {image.cols() + 2*t_mid};
19+
// Allocate result image.
20+
Matrix new_image(x_max, y_max);
21+
// Do convolution
22+
for (int x = 0; x < x_max; ++x) {
23+
for (int y = 0; y < y_max; ++y) {
24+
// Calculate pixel value for h at (x,y). Sum one component
25+
// for each pixel (s, t) of the filter kernel.
26+
auto s_from {std::max(s_mid - x, -s_mid)};
27+
auto s_to {std::min((x_max - x) - s_mid, s_mid + 1)};
28+
auto t_from {std::max(t_mid - y, -t_mid)};
29+
auto t_to {std::min((y_max - y) - t_mid, t_mid + 1)};
30+
double value {0.0};
31+
for (int s = s_from; s < s_to; ++s) {
32+
for (int t = t_from; t < t_to; ++t) {
33+
auto v {x - s_mid + s};
34+
auto w {y - t_mid + t};
35+
value += kernel(s_mid - s, t_mid - t)*image(v, w);
36+
}
37+
}
38+
new_image(x, y) = value;
39+
}
40+
}
41+
return new_image;
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef CONVOLUTION_HDR
2+
#define CONVOLUTION_HDR
3+
4+
#include "matrices.h"
5+
6+
/**
7+
* @brief Compute the convolution of an image with a kernel.
8+
* @param image The image to convolve. This is a 2D matrix with m rows and n columns.
9+
* @param kernel The kernel to convolve with. This is a 2D matrix with k rows and l columns,
10+
* where k and l ard odd integers.
11+
* @return The result of the convolution. This is a 2D matrix with m + k - 1 rows
12+
* and n + l -1 columns.
13+
*/
14+
Matrix convolve(const Matrix& image, const Matrix& kernel);
15+
16+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "matrices.h"
2+
3+
Matrix::Matrix(const Matrix& other) :
4+
rows_(other.rows_), cols_(other.cols_),
5+
data_(new double[rows_ * cols_]) {
6+
for (int i = 0; i < rows_ * cols_; ++i) {
7+
data_[i] = other.data_[i];
8+
}
9+
}
10+
11+
Matrix& Matrix::operator=(const Matrix& other) {
12+
if (this != &other) {
13+
rows_ = other.rows_;
14+
cols_ = other.cols_;
15+
data_.reset(new double[rows_ * cols_]);
16+
for (int i = 0; i < rows_ * cols_; ++i) {
17+
data_[i] = other.data_[i];
18+
}
19+
}
20+
return *this;
21+
}
22+
Matrix::Matrix(Matrix&& other) noexcept :
23+
rows_{other.rows_}, cols_{other.cols_},
24+
data_{std::move(other.data_)} {
25+
other.rows_ = 0;
26+
other.cols_ = 0;
27+
}
28+
29+
Matrix& Matrix::operator=(Matrix&& other) noexcept {
30+
if (&other != this) {
31+
rows_ = other.rows_;
32+
cols_ = other.cols_;
33+
data_ = std::move(other.data_);
34+
35+
other.rows_ = 0;
36+
other.cols_ = 0;
37+
}
38+
return *this;
39+
}
40+
41+
std::ostream& operator<<(std::ostream& os, const Matrix& m) {
42+
for (int i = 0; i < m.rows_; ++i) {
43+
for (int j = 0; j < m.cols_; ++j) {
44+
os << m(i, j) << " ";
45+
}
46+
os << std::endl;
47+
}
48+
return os;
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef MATRICES_HDR
2+
#define MATRICES_HDR
3+
4+
#include <iostream>
5+
#include <memory>
6+
7+
8+
struct Matrix {
9+
private:
10+
int rows_;
11+
int cols_;
12+
std::unique_ptr<double[]> data_;
13+
public:
14+
Matrix(int rows, int cols) :
15+
rows_(rows), cols_(cols), data_(new double[rows * cols]) {}
16+
// copy constructor & assignment operator
17+
Matrix(const Matrix& other);
18+
Matrix& operator=(const Matrix& other);
19+
// move constructor & assignment operator
20+
Matrix(Matrix&& other) noexcept;
21+
Matrix& operator=(Matrix&& other) noexcept;
22+
// matrix indexing by row and column
23+
double& operator()(int i, int j) { return data_[i * cols_ + j]; }
24+
double operator()(int i, int j) const { return data_[i * cols_ + j]; }
25+
// getters for number of rows and columns
26+
int rows() const { return rows_; }
27+
int cols() const { return cols_; }
28+
// accessors for the data
29+
double* data() { return data_.get(); }
30+
const double* data() const { return data_.get(); }
31+
// destructor
32+
~Matrix() = default;
33+
// textual representation of the matrix
34+
friend std::ostream& operator<<(std::ostream& os, const Matrix& m);
35+
};
36+
37+
#endif

0 commit comments

Comments
 (0)