Skip to content

Instantly share code, notes, and snippets.

@JonathanRaiman
Created October 18, 2016 04:45
Show Gist options
  • Save JonathanRaiman/9e07b7c8e82aa83a8010cfc0726373ae to your computer and use it in GitHub Desktop.
Save JonathanRaiman/9e07b7c8e82aa83a8010cfc0726373ae to your computer and use it in GitHub Desktop.
Cute openmp timing tests
// clang++ openmp.cpp -o openmp -fopenmp -O3 -std=c+11
#include <cassert>
#include <stdlib.h>
#include <cmath>
#include <omp.h>
#include <iostream>
template<typename T>
struct Vector {
T* ptr_;
int n_;
Vector(int n) : ptr_((T*)malloc(n * sizeof(T))), n_(n) {
}
~Vector() {
free(ptr_);
}
void fill(T val) {
for (int i = 0; i < n_; i++) {
ptr_[i] = val;
}
}
void print(int max_num=-1) const {
if (max_num < 0) {
max_num = n_;
} else if (max_num > n_) {
max_num = n_;
}
std::cout << "[";
for (int i = 0; i < max_num; i++) {
std::cout << ptr_[i] << " ";
}
std::cout << "]";
std::cout << std::endl;
}
};
inline float fast_tanh(float x) {
return (1.0f - expf(- 2.0f * x)) / (1.0f + expf(- 2.0f * x));
}
struct FastTanh {
template<typename T>
inline static void Map(T& res, const T& left, const T& right) {
res = fast_tanh(left) + right;
}
};
struct RegularTanh {
template<typename T>
inline static void Map(T& res, const T& left, const T& right) {
res = tanh(left) + right;
}
};
template<typename Functor, typename T>
void add_simd(const Vector<T>& a, const Vector<T>& b, Vector<T>* out_ptr) {
auto& out = *out_ptr;
assert(out.n_ == a.n_);
assert(out.n_ == b.n_);
#pragma clang loop vectorize(enable) interleave(enable)
for (int i = 0; i < out.n_; i++) {
Functor::Map(out.ptr_[i], a.ptr_[i], b.ptr_[i]);
}
}
template<typename Functor, typename T>
void add_parallel(const Vector<T>& a, const Vector<T>& b, Vector<T>* out_ptr) {
auto& out = *out_ptr;
assert(out.n_ == a.n_);
assert(out.n_ == b.n_);
#pragma omp parallel for collapse(1)
for (int i = 0; i < out.n_; i++) {
Functor::Map(out.ptr_[i], a.ptr_[i], b.ptr_[i]);
}
}
template<typename Functor, typename T>
void add_hybrid(const Vector<T>& a, const Vector<T>& b, Vector<T>* out_ptr) {
auto& out = *out_ptr;
assert(out.n_ == a.n_);
assert(out.n_ == b.n_);
#pragma omp parallel for simd
for (int i = 0; i < out.n_; i++) {
Functor::Map(out.ptr_[i], a.ptr_[i], b.ptr_[i]);
}
}
int main(int argc, char** argv) {
if (argc < 2) {
std::cout << argv[0] << " [N]" << std::endl;
exit(1);
}
int n = std::atoi(argv[1]);
assert(n > 0);
Vector<float> out(n);
Vector<float> a(n);
Vector<float> b(n);
out.fill(0);
a.fill(1);
b.fill(2);
double Start, End;
typedef RegularTanh Functor;
for (int i = 0; i < 10; i++) {
add_simd<Functor>(a, b, &out);
}
for (int i = 0; i < 10; i++) {
add_hybrid<Functor>(a, b, &out);
}
for (int i = 0; i < 10; i++) {
add_parallel<Functor>(a, b, &out);
}
Start = omp_get_wtime();
for (int i = 0; i < 10; i++) {
add_simd<Functor>(a, b, &out);
}
End = omp_get_wtime();
std::cout << "simd Delta t2-t1: "
<< End - Start
<< " seconds" << std::endl;
Start = omp_get_wtime();
for (int i = 0; i < 10; i++) {
add_hybrid<Functor>(a, b, &out);
}
End = omp_get_wtime();
std::cout << "hybrid Delta t2-t1: "
<< End - Start
<< " seconds" << std::endl;
Start = omp_get_wtime();
for (int i = 0; i < 10; i++) {
add_parallel<Functor>(a, b, &out);
}
End = omp_get_wtime();
std::cout << "parallel Delta t2-t1: "
<< End - Start
<< " seconds" << std::endl;
for (int i=0; i < 10000; i++) {
for (int i = 0; i < 10; i++) {
add_hybrid<Functor>(a, b, &out);
}
}
out.print(100);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment