我感兴趣的是将我使用Thrust GPU库编写的代码移植到多核CPU上。值得庆幸的是,the website表示推力代码可以用于线程环境,例如OpenMP / Intel TBB。
我在下面编写了一个简单的代码,用于对大型数组进行排序,以便使用可支持最多16个Open MP线程的机器查看加速。
在这台机器上获得的用于分类大小为1600万的随机数组的时间是
STL:1.47 s似乎几乎没有任何加速。我想知道如何使用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;
}
答案 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样式多线程的任何改进。