使用openmp的推力:没有获得实质性的加速

时间:2014-10-17 19:49:53

标签: multithreading sorting thrust

我感兴趣的是将我使用Thrust GPU库编写的代码移植到多核CPU上。值得庆幸的是,the website表示推力代码可以用于线程环境,例如OpenMP / Intel TBB。

我在下面编写了一个简单的代码,用于对大型数组进行排序,以便使用可支持最多16个Open MP线程的机器查看加速。

在这台机器上获得的用于分类大小为1600万的随机数组的时间是

STL:1.47 s
推力(16线程):1.21秒

似乎几乎没有任何加速。我想知道如何使用OpenMP大幅加速排序数组,就像我使用GPU一样。

代码如下(文件sort.cu)。编制如下:

nvcc -O2 -o sort sort.cu -Xcompiler -fopenmp -DTHRUST_DEVICE_SYSTEM = THRUST_DEVICE_BACKEND_OMP -lgomp

NVCC版本是5.5 正在使用的Thrust库版本是v1.7.0

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <stdio.h>
#include <algorithm>    
#include <ctime>
#include <time.h>
#include "thrust/sort.h"    

int main(int argc, char *argv[])
{
  int N = 16000000;
  double* myarr = new double[N];

  for (int i = 0; i < N; ++i)
    {
      myarr[i] = (1.0*rand())/RAND_MAX; 
     }
  std::cout << "-------------\n";

  clock_t start,stop;
  start=clock();
  std::sort(myarr,myarr+N);
  stop=clock();

  std::cout << "Time taken for sorting the array with STL  is " << (stop-start)/(double)CLOCKS_PER_SEC;

  //--------------------------------------------

  srand(1);
  for (int i = 0; i < N; ++i)
    {
      myarr[i] = (1.0*rand())/RAND_MAX; 
      //std::cout << myarr[i] << std::endl;
     }

  start=clock();
  thrust::sort(myarr,myarr+N);
  stop=clock();

  std::cout << "------------------\n";


  std::cout << "Time taken for sorting the array with Thrust  is " << (stop-start)/(double)CLOCKS_PER_SEC;
  return 0;
}

1 个答案:

答案 0 :(得分:2)

device backend refers to the behavior of operations performed on a thrust::device_vector或类似的参考。 Thrust解释您将其作为主机指针传递的数组/指针,并对其执行基于主机的操作,这些操作不受设备后端设置的影响。

有多种方法可以解决此问题。如果您阅读设备后端文档,您将找到一般示例和特定于omp的示例。您甚至可以指定一个不同的host backend,它应该具有您的代码所需的行为(OMP使用),我认为。

一旦你解决了这个问题,你可能会得到额外的结果惊喜:推力似乎可以快速排序数组,但报告的执行时间非常长。我相信这是(在linux上,无论如何)到the clock() function being affected by the number of OMP threads in use

以下代码/示例运行解决了这些问题,并且似乎为4个线程提供了~3倍的加速。

$ cat t592.cu
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <stdio.h>
#include <algorithm>
#include <ctime>
#include <sys/time.h>
#include <time.h>
#include <thrust/device_ptr.h>
#include <thrust/sort.h>

int main(int argc, char *argv[])
{
  int N = 16000000;
  double* myarr = new double[N];

  for (int i = 0; i < N; ++i)
    {
      myarr[i] = (1.0*rand())/RAND_MAX;
     }
  std::cout << "-------------\n";

  timeval t1, t2;
  gettimeofday(&t1, NULL);
  std::sort(myarr,myarr+N);
  gettimeofday(&t2, NULL);
  float et = (((t2.tv_sec*1000000)+t2.tv_usec)-((t1.tv_sec*1000000)+t1.tv_usec))/float(1000000);

  std::cout << "Time taken for sorting the array with STL  is " << et << std::endl;;

  //--------------------------------------------

  srand(1);
  for (int i = 0; i < N; ++i)
    {
      myarr[i] = (1.0*rand())/RAND_MAX;
      //std::cout << myarr[i] << std::endl;
     }
  thrust::device_ptr<double> darr = thrust::device_pointer_cast<double>(myarr);
  gettimeofday(&t1, NULL);
  thrust::sort(darr,darr+N);
  gettimeofday(&t2, NULL);
  et = (((t2.tv_sec*1000000)+t2.tv_usec)-((t1.tv_sec*1000000)+t1.tv_usec))/float(1000000);

  std::cout << "------------------\n";


  std::cout << "Time taken for sorting the array with Thrust  is " << et << std::endl   ;
  return 0;
}

$ nvcc -O2 -o t592 t592.cu -Xcompiler -fopenmp -DTHRUST_DEVICE_SYSTEM=THRUST_DEVICE_BACKEND_OMP -lgomp
$ OMP_NUM_THREADS=4 ./t592
-------------
Time taken for sorting the array with STL  is 1.31956
------------------
Time taken for sorting the array with Thrust  is 0.468176
$

您的里程可能会有所不同。特别是,当您超过4个线程时,您可能看不到任何改进。可能有许多因素阻止OMP代码扩展超过一定数量的线程。排序通常倾向于是一种内存限制算法,因此您可能会观察到增加,直到您使内存子系统饱和,然后不再增加其他内核。根据您的系统,您可能已经处于这种情况,在这种情况下,您可能看不到OMP样式多线程的任何改进。