标签: openmp

为什么编译器在循环中从内存加载此指针

我试图确定std::atomic在我的系统(八核x64)上无条件内存写入的开销.这是我的基准程序:

#include <atomic>
#include <iostream>
#include <omp.h>

int main() {
    std::atomic_int foo(0); // VERSION 1
    //volatile int foo = 0; // VERSION 2

    #pragma omp parallel
    for (unsigned int i = 0; i < 10000000; ++i) {
        foo.store(i, std::memory_order_relaxed); // VERSION 1
        //foo = i; // VERSION 2
    }

    std::cout << foo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

该程序将按原样进行基准测试std::atomic_int,并对标记VERSION 1的行进行注释并取消注释标记的VERSION 2行将volatile int在其位置进行测试.即使不同步,两个程序的输出也应为10000000 - 1.

这是我的命令行:

g++ -O2 -std=c++11 -fopenmp test.c++
Run Code Online (Sandbox Code Playgroud)

atomic_int在我的系统上使用的版本需要2到3秒,而使用的版本volatile …

c++ performance multithreading atomic openmp

12
推荐指数
1
解决办法
282
查看次数

为什么OpenMP版本更慢?

我正在试验OpenMP.我写了一些代码来检查它的性能.在使用Kubuntu 11.04的4核单Intel CPU上,使用OpenMP编译的以下程序比没有OpenMP编译的程序慢大约20倍.为什么?

我用g ++编译了它-g -O2 -funroll-loops -fomit-frame-pointer -march = native -fopenmp

#include <math.h>
#include <iostream>

using namespace std;

int main ()
{
  long double i=0;
  long double k=0.7;

  #pragma omp parallel for reduction(+:i)
  for(int t=1; t<300000000; t++){       
    for(int n=1; n<16; n++){
      i=i+pow(k,n);
    }
  }

  cout << i<<"\t";
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ openmp

11
推荐指数
1
解决办法
1万
查看次数

如何在C代码中获取变量的类型?

有没有什么方法可以通过程序本身的某种机制在C中自动发现变量的类型,或者 - 更有可能 - 通过使用编译器的预编译脚本传递到它的位置解析了变量并为它们分配了类型?我正在寻找关于此的一般性建议.下面是关于我需要什么以及为什么的更多背景.

我想改变OpenMP减少子句的语义.在这一点上,简单地通过调用函数替换源代码中的子句(通过脚本)似乎是最容易的,然后我可以定义函数来实现我想要的缩减语义.例如,我的脚本会转换它

#pragma omp parallel for reduction(+:x)
Run Code Online (Sandbox Code Playgroud)

进入这个:

my_reduction(PLUS, &x, sizeof(x));
#pragma omp parallel for
Run Code Online (Sandbox Code Playgroud)

在哪里,我早些时候(说)

enum reduction_op {PLUS, MINUS, TIMES, AND,
  OR, BIT_AND, BIT_OR, BIT_XOR, /* ... */};
Run Code Online (Sandbox Code Playgroud)

my_reduction签名

void my_reduction(enum reduction_op op, void * var, size_t size);
Run Code Online (Sandbox Code Playgroud)

除其他外,my_reduction必须像程序员最初预期的那样将加法运算应用于约简变量.但我的功能无法知道如何正确地做到这一点.特别是,尽管它知道operation(PLUS)var的类型,原始变量()的位置以及变量类型的大小,但它不知道变量的类型本身.特别是,它不知道是否var具有整数或浮点类型.从低级别POV来看,这两类类型的加法操作完全不同.

如果只有typeofGCC支持的非标准运算符可以像sizeof一样工作 - 返回某种类型的变量 - 我可以轻松地解决这个问题.但是typeof并不像sizeof:它只能在l值声明中使用.

现在,编译器显然在完成生成可执行代码之前就知道了x的类型.这让我想知道我是否可以某种方式利用GCC的解析器,只是获取x类型并将其传递给我的脚本,然后再一次运行GCC来编译我修改过的源代码.那么宣布就足够简单了

enum var_type { INT8, UINT8, INT16, UINT16, /* ,..., */ FLOAT, DOUBLE};
void my_reduction(enum reduction_op op, …
Run Code Online (Sandbox Code Playgroud)

c gcc types typeof openmp

11
推荐指数
3
解决办法
2万
查看次数

4个核心的8个逻辑线程最多可以并行运行4倍?

我是基准测试软件,它在Intel 2670QM上运行速度提高了4倍,然后我的串行版本使用了所有8个"逻辑"线程.我希望社群对我对基准测试结果看法有所反馈.

当我在4个核心上使用4个线程时,我的速度提高了4倍,整个算法都是并行执行的.这对我来说似乎合乎逻辑,因为'Amdhals law'预测它.Windows任务管理器告诉我,我正在使用50%的CPU.

但是如果我在所有8个线程上执行相同的软件,我再次获得4倍的速度而不是 8倍的速度.

如果我已正确理解这一点:我的CPU有4个内核,频率为2.2GHZ,但当应用于8个'逻辑'线程时,频率被分为1.1GHZ,其余部分如高速缓冲存储器也是如此. ?如果这是真的那么为什么任务管理器只声称我的CPU有50%被使用?

#define NumberOfFiles 8
...
char startLetter ='a';
#pragma omp parallel for shared(startLetter)
for(int f=0; f<NumberOfFiles; f++){
    ...
}
Run Code Online (Sandbox Code Playgroud)

我不包括使用磁盘I/O的时间.我只对STL调用(STL排序)而不是磁盘I/O的时间感兴趣.

multithreading multicore openmp

11
推荐指数
3
解决办法
3万
查看次数

OpenMP time和clock()计算两个不同的结果

我有通过OpenMP并行化的顺序代码.我已经放了相应的pragma并测试它.在测试时,我通过检查主要功能所花费的时间来解释性能提升.奇怪的是通过计算的经过时间cpu_time()omp_get_wtime()返回两个不同的结果.您认为原因是什么?

通过cpu_time()函数计算的经过时间与顺序时间类似.

在计算开始之前

ctime1_ = cpu_time();
#ifdef _OPENMP
ctime1 = omp_get_wtime();
#endif
Run Code Online (Sandbox Code Playgroud)

计算结束后

ctime2_ = cpu_time();
#ifdef _OPENMP
ctime2 = omp_get_wtime();
#endif
Run Code Online (Sandbox Code Playgroud)

cpu_time()函数定义

double cpu_time(void)
{
  double value;
  value = (double) clock () / (double) CLOCKS_PER_SEC;
  return value;
}
Run Code Online (Sandbox Code Playgroud)

打印结果

printf("%f - %f seconds.\n", ctime2 - ctime1, ctime2_ - ctime1_);
Run Code Online (Sandbox Code Playgroud)

样本结果

7.009537 - 11.575277 seconds.
Run Code Online (Sandbox Code Playgroud)

c openmp

11
推荐指数
3
解决办法
2万
查看次数

OpenMP with MSVC 2010 Debug在复制对象时构建奇怪的bug

我有一个相当复杂的程序,在MSVC 2010调试模式下使用OpenMP构建时会遇到奇怪的行为.我尽力构建以下最小的工作示例(虽然它并不是真正的最小化),这样可以简化真实程序的结构.

#include <vector>
#include <cassert>

// A class take points to the whole collection and a position Only allow access
// to the elements at that posiiton. It provide read-only access to query some
// information about the whole collection
class Element
{
    public :

    Element (int i, std::vector<double> *src) : i_(i), src_(src) {}

    int i () const {return i_;}
    int size () const {return src_->size();}

    double src () const {return (*src_)[i_];}
    double &src () {return (*src_)[i_];}

    private : …
Run Code Online (Sandbox Code Playgroud)

c++ openmp visual-c++

11
推荐指数
1
解决办法
1506
查看次数

基于任务的编程:#pragma omp task与#pragma omp parallel for

考虑:

    void saxpy_worksharing(float* x, float* y, float a, int N) {
      #pragma omp parallel for
      for (int i = 0; i < N; i++) {
         y[i] = y[i]+a*x[i];
      }
    }
Run Code Online (Sandbox Code Playgroud)

    void saxpy_tasks(float* x, float* y, float a, int N) {
      #pragma omp parallel
      {
         for (int i = 0; i < N; i++) {
         #pragma omp task
         {
           y[i] = y[i]+a*x[i];
         }
      }
   }
Run Code Online (Sandbox Code Playgroud)

使用任务和omp并行指令有什么区别?为什么我们可以编写递归算法,例如与任务合并排序,而不是与工作共享?

task openmp

11
推荐指数
1
解决办法
2万
查看次数

不确定openmp循环中应该是SHARED还是PRIVATE

我有一个更新矩阵A的循环,我想让它变为openmp但我不确定应该共享哪些变量和私有.我本以为只有ii和jj会起作用,但事实并非如此.我想我也需要一个!$ OMP ATOMIC UPDATE ...

循环只计算N和N-1粒子之间的距离并更新矩阵A.

            !$OMP PARALLEL DO PRIVATE(ii,jj)
            do ii=1,N-1
                    do jj=ii+1,N
                            distance_vector=X(ii,:)-X(jj,:)
                            distance2=sum(distance_vector*distance_vector)
                            distance=DSQRT(distance2)
                            coff=distance*distance*distance
                            PE=PE-M(II)*M(JJ)/distance
                            A(jj,:)=A(jj,:)+(M(ii)/coff)*(distance_vector)
                            A(ii,:)=A(ii,:)-(M(jj)/coff)*(distance_vector)
                    end do
            end do
            !$OMP END PARALLEL DO
Run Code Online (Sandbox Code Playgroud)

parallel-processing fortran loops openmp

11
推荐指数
1
解决办法
2万
查看次数

使用SSE,AVX和OpenMP进行快速内存转置

我需要一个快速的内存转置算法,用于C/C++中的高斯卷积函数.我现在做的是

convolute_1D
transpose
convolute_1D
transpose
Run Code Online (Sandbox Code Playgroud)

事实证明,使用这种方法,滤波器的大小必须很大(或大于我的预期),或者转置需要比卷积更长的时间(例如,对于1920x1080矩阵,卷积与转置的时间相同,滤波器大小为35 ).我正在使用的当前转置算法使用循环阻塞/平铺以及SSE和OpenMP.我尝试过使用AVX的版本,但速度并不快.关于如何加快速度的任何建议?

inline void transpose4x4_SSE(float *A, float *B, const int lda, const int ldb) {
    __m128 row1 = _mm_load_ps(&A[0*lda]);
    __m128 row2 = _mm_load_ps(&A[1*lda]);
    __m128 row3 = _mm_load_ps(&A[2*lda]);
    __m128 row4 = _mm_load_ps(&A[3*lda]);
     _MM_TRANSPOSE4_PS(row1, row2, row3, row4);
     _mm_store_ps(&B[0*ldb], row1);
     _mm_store_ps(&B[1*ldb], row2);
     _mm_store_ps(&B[2*ldb], row3);
     _mm_store_ps(&B[3*ldb], row4);
}
//block_size = 16 works best
inline void transpose_block_SSE4x4(float *A, float *B, const int n, const int m, const int lda, const int ldb ,const int block_size) {
    #pragma omp parallel for …
Run Code Online (Sandbox Code Playgroud)

optimization transpose sse openmp avx

11
推荐指数
1
解决办法
5392
查看次数

在多线程程序中使用exprtk

我需要编写一个程序,其中频繁地评估字符串表达式.表达式的示例如下:

"x0*a0*a0+x1*a1+x2*a2+x3*a3+x4*a4....."
Run Code Online (Sandbox Code Playgroud)

表达式可以很长,字符串可以包含多个这样的表达式.

我使用C++库exprtk编写了一些测试代码.

vector<std::string> observation_functions;
vector<std::string> string_indices;


template<typename T>
float* get_observation(float* sing_j, float* zrlist, int num_functions,int num_variables)
{
    //omp_set_nested(1);

    float* results = (float*)malloc(sizeof(float)*num_functions);
    exprtk::symbol_table<float> symbol_table;

    exprtk::expression<T> expression;
    exprtk::parser<T> parser;
    int i;
    for( i = 0; i < num_variables; i++)
    {
            symbol_table.add_variable("x"+string_indices[i], sing_j[i]);
            symbol_table.add_variable("a"+string_indices[i], zrlist[i]);
    }

    expression.register_symbol_table(symbol_table);
    for(i = 0; i < num_functions; i++)
    {
            parser.compile(observation_functions[i],expression);
            results[i] = expression.value();
    }
    return results;
}



int main()
{

    for( int i = 0; i < 52; i++)
    {

    ostringstream s2;
    s2<<i;
    string_indices.push_back(s2.str()); …
Run Code Online (Sandbox Code Playgroud)

c++ performance multithreading openmp exprtk

11
推荐指数
2
解决办法
1065
查看次数