Skip to content

Commit

Permalink
Merge pull request #20 from gjbex/development
Browse files Browse the repository at this point in the history
Add slides on I/O
  • Loading branch information
gjbex authored Feb 3, 2024
2 parents fecc51d + 41c4e35 commit 47bed4d
Show file tree
Hide file tree
Showing 28 changed files with 1,645 additions and 3,983 deletions.
56 changes: 56 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
layout: page
title: Code of conduct
permalink: /code_of_conduct.html
---

# Code of conduct

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.

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.


## Expected behavior

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:

* Use welcoming and inclusive language
* Be respectful of different viewpoints and experiences
* Gracefully accept constructive criticism
* Focus on what is best for the community
* Show courtesy and respect towards other community members


## Unacceptable behavior

Examples of unacceptable behavior by participants at any workshop event/platform include:

* written or verbal comments which have the effect of excluding people on the basis of membership of any specific group
* causing someone to fear for their safety, such as through stalking, following, or intimidation
* violent threats or language directed against another person
* the display of sexual or violent images
* unwelcome sexual attention
* nonconsensual or unwelcome physical contact
* sustained disruption of talks, events or communications
* insults or put downs
* sexist, racist, homophobic, transphobic, ableist, or exclusionary jokes
* excessive swearing
* incitement to violence, suicide, or self-harm
* continuing to initiate interaction (including photography or recording) with someone after being asked to stop
* publication of private communication without consent
* sharing recordings of training sessions with non-participants


## Consequences of Unacceptable behavior

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.

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.

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.


## Attribution

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).
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ GitHub repository for participants of the "Python for HPC" training.
For information on the training, see the website
[https://gjbex.github.io/Python-for-HPC/](https://gjbex.github.io/Python-for-HPC/)

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


## What is it?

Expand All @@ -15,3 +18,5 @@ For information on the training, see the website
1. [Contributing](CONTRIBUTING.md): information on how to contribute to this
repository.
1. docs: directory containing the website for this repository.
1. [Code of conduct](CODE_OF_CONDUCT.md): when participating in this training
you accept to abide by the code of conduct.
Binary file modified python_for_hpc.pptx
Binary file not shown.
10 changes: 5 additions & 5 deletions source-code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ to create it. There is some material not covered in the presentation as well.
* Packages (names listed taht can be used with `pip` or `conda` to install):
* cython
* dask
* numba
* numpy
* numexpr
* scipy
Expand All @@ -19,10 +20,6 @@ to create it. There is some material not covered in the presentation as well.
* jupyter
* ipywidgets

* For the GPU code:
* pycuda
* scikit-cuda


## What is it?

Expand All @@ -43,5 +40,8 @@ to create it. There is some material not covered in the presentation as well.
1. `numpy-scipy`: some numpy/scipy codes for benchmakring.
1. `pypy`: code to experiment with the Pypy interpreter.
1. `file-formats`: influcence of file formats on performance.
1. `gpu`: some examples of using GPUs.
1. `performance`: general considerations about performance.
1. `convolution`: wrap up exercise to apply all techniques.

**Note:** the GPU code in this repository was moved to
[its own repository](https://github.com/gjbex/Python-on-GPUs)
21 changes: 21 additions & 0 deletions source-code/convolution/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Convolution

Convolution of an image using a kernel makes a nice problem to implement
using various HPC technologies. It is conceptually simple enough to be used
as an exercise, yet computationally sufficiently challenging to make it
interesting.

To get you started, you get a
* [Python](python) implementations, and
* [C++](cpp) implementation.


You can try to:

* use numba,
* use Cython,
* use Swig to bind the C++ implementation,
* use PyBind11 to bind the C++ implementation,
* parallelize the code using Cython,
* parallelize the code using multiprocessing,
* parallelize and run the application on multiple nodes MPI.
10 changes: 10 additions & 0 deletions source-code/convolution/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.18)
project(algorithms LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMaKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS NO)

add_compile_options(-Wall -Wextra -Wpedantic)

add_subdirectory(src)
12 changes: 12 additions & 0 deletions source-code/convolution/cpp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# C++ implementation

This is a (pretty naive) C++ implementation of 2D convolution.


## What is it?

1. `src/convolution/convolution.h`: declaration of the convolution function.
1. `src/convolution/convolution.cpp`: definition of the convolution function.
1. `src/benchmark_convolution.cpp`: a C++ application to benchmark the
implementation.
1. `src/test_convolution.cpp`: a C++ application to test the implementation.
15 changes: 15 additions & 0 deletions source-code/convolution/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
add_subdirectory(convolution)

add_executable(test_convolution.exe
test_convolution.cpp)
target_include_directories(test_convolution.exe
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/convolution)
target_link_libraries(test_convolution.exe
PRIVATE convolution)

add_executable(benchmark_convolution.exe
benchmark_convolution.cpp)
target_include_directories(benchmark_convolution.exe
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/convolution)
target_link_libraries(benchmark_convolution.exe
PRIVATE convolution)
57 changes: 57 additions & 0 deletions source-code/convolution/cpp/src/benchmark_convolution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <convolution.h>
#include <chrono>
#include <iostream>
#include <numeric>
#include <random>

Matrix create_image(int rows, int cols) {
std::mt19937 gen(1234);
std::uniform_real_distribution<double> dis(0.0, 1.0);
Matrix image(rows, cols);
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
image(i, j) = dis(gen);
}
}
return image;
}

Matrix create_kernel(int rows, int cols) {
Matrix kernel(rows, cols);
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
kernel(i, j) = 1.0/(rows*cols);
}
}
return kernel;
}

double element_sum(const Matrix& matrix) {
return std::accumulate(matrix.data(), matrix.data() + matrix.rows()*matrix.cols(), 0.0);
}

int main(int argc, char** argv) {
int rows = 1000;
int cols = 1000;
int kernel_rows = 7;
int kernel_cols = 7;
if (argc > 1) {
rows = atoi(argv[1]);
cols = atoi(argv[1]);
}
if (argc > 2) {
kernel_rows = atoi(argv[2]);
kernel_cols = atoi(argv[2]);
}
std::cout << "Image size: " << rows << "x" << cols << "\n";
std::cout << "Kernel size: " << kernel_rows << "x" << kernel_cols << "\n";
Matrix image = create_image(rows, cols);
Matrix kernel = create_kernel(kernel_rows, kernel_cols);
auto start = std::chrono::high_resolution_clock::now();
auto result = convolve(image, kernel);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "Time: " << diff.count() << " s\n";
std::cout << "Sum: " << element_sum(result) << "\n";
return 0;
}
2 changes: 2 additions & 0 deletions source-code/convolution/cpp/src/convolution/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_library(convolution SHARED
convolution.cpp matrices.cpp)
42 changes: 42 additions & 0 deletions source-code/convolution/cpp/src/convolution/convolution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "convolution.h"
#include <exception>

Matrix convolve(const Matrix& image, const Matrix& kernel) {
if (kernel.rows() % 2 != 1 || kernel.cols() % 2 != 1) {
throw std::invalid_argument("Only odd dimensions on kernel supported");
}
/*
s_mid and t_mid are number of pixels between the center pixel
and the edge, ie for a 5x5 filter they will be 2.
The output size is calculated by adding s_mid, t_mid to each
side of the dimensions of the input image.
*/
auto s_mid {kernel.rows()/2};
auto t_mid {kernel.cols()/2};
auto x_max {image.rows() + 2*s_mid};
auto y_max {image.cols() + 2*t_mid};
// Allocate result image.
Matrix new_image(x_max, y_max);
// Do convolution
for (int x = 0; x < x_max; ++x) {
for (int y = 0; y < y_max; ++y) {
// Calculate pixel value for h at (x,y). Sum one component
// for each pixel (s, t) of the filter kernel.
auto s_from {std::max(s_mid - x, -s_mid)};
auto s_to {std::min((x_max - x) - s_mid, s_mid + 1)};
auto t_from {std::max(t_mid - y, -t_mid)};
auto t_to {std::min((y_max - y) - t_mid, t_mid + 1)};
double value {0.0};
for (int s = s_from; s < s_to; ++s) {
for (int t = t_from; t < t_to; ++t) {
auto v {x - s_mid + s};
auto w {y - t_mid + t};
value += kernel(s_mid - s, t_mid - t)*image(v, w);
}
}
new_image(x, y) = value;
}
}
return new_image;
}
16 changes: 16 additions & 0 deletions source-code/convolution/cpp/src/convolution/convolution.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef CONVOLUTION_HDR
#define CONVOLUTION_HDR

#include "matrices.h"

/**
* @brief Compute the convolution of an image with a kernel.
* @param image The image to convolve. This is a 2D matrix with m rows and n columns.
* @param kernel The kernel to convolve with. This is a 2D matrix with k rows and l columns,
* where k and l ard odd integers.
* @return The result of the convolution. This is a 2D matrix with m + k - 1 rows
* and n + l -1 columns.
*/
Matrix convolve(const Matrix& image, const Matrix& kernel);

#endif
49 changes: 49 additions & 0 deletions source-code/convolution/cpp/src/convolution/matrices.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "matrices.h"

Matrix::Matrix(const Matrix& other) :
rows_(other.rows_), cols_(other.cols_),
data_(new double[rows_ * cols_]) {
for (int i = 0; i < rows_ * cols_; ++i) {
data_[i] = other.data_[i];
}
}

Matrix& Matrix::operator=(const Matrix& other) {
if (this != &other) {
rows_ = other.rows_;
cols_ = other.cols_;
data_.reset(new double[rows_ * cols_]);
for (int i = 0; i < rows_ * cols_; ++i) {
data_[i] = other.data_[i];
}
}
return *this;
}
Matrix::Matrix(Matrix&& other) noexcept :
rows_{other.rows_}, cols_{other.cols_},
data_{std::move(other.data_)} {
other.rows_ = 0;
other.cols_ = 0;
}

Matrix& Matrix::operator=(Matrix&& other) noexcept {
if (&other != this) {
rows_ = other.rows_;
cols_ = other.cols_;
data_ = std::move(other.data_);

other.rows_ = 0;
other.cols_ = 0;
}
return *this;
}

std::ostream& operator<<(std::ostream& os, const Matrix& m) {
for (int i = 0; i < m.rows_; ++i) {
for (int j = 0; j < m.cols_; ++j) {
os << m(i, j) << " ";
}
os << std::endl;
}
return os;
}
37 changes: 37 additions & 0 deletions source-code/convolution/cpp/src/convolution/matrices.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef MATRICES_HDR
#define MATRICES_HDR

#include <iostream>
#include <memory>


struct Matrix {
private:
int rows_;
int cols_;
std::unique_ptr<double[]> data_;
public:
Matrix(int rows, int cols) :
rows_(rows), cols_(cols), data_(new double[rows * cols]) {}
// copy constructor & assignment operator
Matrix(const Matrix& other);
Matrix& operator=(const Matrix& other);
// move constructor & assignment operator
Matrix(Matrix&& other) noexcept;
Matrix& operator=(Matrix&& other) noexcept;
// matrix indexing by row and column
double& operator()(int i, int j) { return data_[i * cols_ + j]; }
double operator()(int i, int j) const { return data_[i * cols_ + j]; }
// getters for number of rows and columns
int rows() const { return rows_; }
int cols() const { return cols_; }
// accessors for the data
double* data() { return data_.get(); }
const double* data() const { return data_.get(); }
// destructor
~Matrix() = default;
// textual representation of the matrix
friend std::ostream& operator<<(std::ostream& os, const Matrix& m);
};

#endif
Loading

0 comments on commit 47bed4d

Please sign in to comment.