I have a simple matrix class which I'd like to vectorize its add operator. However, uniform this seems not to be supported under GCC (works fine using Intel C++ Compiler). I am curios if there is any workaround. (below is the code along compile command)
Please let me know if you have any comments.
#include <iostream>
#include <cassert>
#include <omp.h>
#define printvar(a) std::cerr << (#a) << " = " << (a) << std::endl;
#define printline std::cerr << "FILE " << __FILE__ << " LINE " << __LINE__ << " FUNC: " << __func__ << std::endl;
#define NUMEL 10000
#pragma omp declare simd simdlen(2)
#pragma omp declare simd simdlen(4)
#pragma omp declare simd simdlen(8)
#pragma omp declare simd simdlen(16)
int myadd(int a, int b){
return a+b;
}
template <typename V>
class Matrix {
public:
V* data;
int nrows, ncols;
bool istemp = false;
std::string name;
Matrix(){
data = NULL;
}
Matrix(int nrows, int ncols, V val, std::string name = "none"){
this->nrows = nrows;
this->ncols = ncols;
this->name = name;
data = (V*) malloc(sizeof(V)*nrows*ncols);
for(int i = 0; i < numel(); i++){
csi0(i) = val;
}
}
Matrix(const Matrix& m){
this->nrows = m.nrows;
this->ncols = m.ncols;
this->data = (V*) malloc(sizeof(V)*nrows*ncols);
for(int i = 0; i < numel(); i++){
csi0(i) = m.csi0(i);
}
}
inline void swap(Matrix<V>& a, Matrix<V>& b){
V* data = a.data; a.data = b.data; b.data = data;
int nrows = a.nrows; a.nrows = b.nrows; b.nrows = nrows;
int ncols = a.ncols; a.ncols = b.ncols; b.ncols = ncols;
}
Matrix<V>& operator=(const Matrix<V>& m){
Matrix<V> tmp(m);
swap(*this,tmp);
}
#pragma omp declare simd
#pragma omp declare simd simdlen(4) uniform(this)
#pragma omp declare simd simdlen(8) uniform(this)
#pragma omp declare simd simdlen(16) uniform(this)
V& csi0 (int i) const {
return this->data[i];
}
V& cij0 (int i, int j) const {
return data[i+nrows*j];
}
int numel() const {
return nrows*ncols;
}
friend Matrix<V> operator+(const Matrix<V>& a, const Matrix<V>& b){
assert(a.nrows == b.nrows && a.ncols == b.ncols);
Matrix<V> retmat(a.nrows, a.ncols, 0, "retmat");
#pragma omp parallel for simd
for(int i = 0; i < a.numel(); i++){
retmat.csi0(i) = a.csi0(i) + b.csi0(i);
}
// retmat.istemp = true;
return retmat;
}
~Matrix(){
if(data != NULL && !istemp){
free(data);
}
}
friend std::ostream& operator<<(std::ostream& os, Matrix<V> m){
os << "{{" << std::endl;
for(int i = 0; i < m.nrows; i++){
for(int j = 0; j < m.ncols; j++){
os << m.csi0(i) << ", ";
}
os << std::endl;
}
os << "}}" << std::endl;
return os;
}
};
int main(int argc, char const *argv[])
{
Matrix<int> a(4,5,1), b(4,5,2), c;
c = a + b;
printvar(c)
}
int main_1(int argc, char const *argv[])
{
int a[NUMEL], b[NUMEL], c[NUMEL];
#pragma omp parallel for
for(int i = 0; i < NUMEL; i++){
c[i] = myadd(a[i], b[i]);
}
return 0;
}
Compile command
g++.exe -fopt-info-all=all.optrpt -O3 -fopenmp -fopenmp-simd -mthreads -mavx -fmax-errors=5 -c gcc_ompsimd_test.cpp -Fo:gcc_ompsimd_test.o
gcc_ompsimd_test.cpp:65:46: error: expected unqualified-id before 'this'
#pragma omp declare simd simdlen(4) uniform(this)
^~~~
gcc_ompsimd_test.cpp:66:46: error: expected unqualified-id before 'this'
#pragma omp declare simd simdlen(8) uniform(this)
^~~~
gcc_ompsimd_test.cpp:67:47: error: expected unqualified-id before 'this'
#pragma omp declare simd simdlen(16) uniform(this)