multithreading - 将推力与openmp一起使用: no substantial speed up obtained

标签 multithreading sorting thrust

我有兴趣将大部分使用Thrust GPU库编写的代码移植到多核CPU。值得庆幸的是,the website说推力代码可以与诸如OpenMP/Intel TBB之类的线程环境一起使用。

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

在此机器上获得的用于排序大小为1600万的随机数组的时间为

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

似乎几乎没有任何提速。我想知道如何像使用GPU一样大幅提高使用OpenMP对数组进行排序的速度。

代码在下面(文件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;
}

最佳答案

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

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

解决此问题后,您可能会得到其他结果惊喜:推力似乎可以快速对数组进行排序,但是执行时间非常长。我相信这是由于the clock() function being affected by the number of OMP threads in use(无论如何在Linux上)。

下面的代码/示例运行解决了这些问题,似乎使我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样式多线程的任何改进。

关于multithreading - 将推力与openmp一起使用: no substantial speed up obtained,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26432462/

相关文章:

Cuda Thrust min_element 崩溃

python - 在Windows上为python编译线程安全的tcl

python - 分析 GIL

Python:如何按对象的特征或属性对对象列表进行分组?

r - 如何对同一列的数据帧列表中的所有数据帧进行排序?

cuda - 常量内存中的推力::device_vector

java - 检查文件是否同时执行

c++ - 使STL对象线程安全的标准方法?

python - 为什么Python需要更长的时间来对列表的副本进行排序?

vector - CUDA推力库: How can I create a host_vector of host_vectors of integers?