我在cuda中使用glm矩阵 - 向量乘法有一些性能问题,在bug tracker中有记录(链接因为它可能对其他人有用)。
在对它进行一些性能测试时,我发现,glm的点积实现比cuda的helper_math.h实现更快
inline __host__ __device__ float dot(float4 a, float4 b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
我试图模仿glm的实现,但性能保持不变:
inline __host__ __device__ float dot(float4 a, float4 b)
{
float4 tmp = a * b;
return (tmp.x + tmp.y) + (tmp.z + tmp.w);
}
这在我看来是glm的实现:
template <typename T, precision P>
struct compute_dot<detail::tvec4, T, P>
{
GLM_FUNC_QUALIFIER static T call(detail::tvec4<T, P> const & x, detail::tvec4<T, P> const & y)
{
detail::tvec4<T, P> tmp(x * y);
return (tmp.x + tmp.y) + (tmp.z + tmp.w);
}
};
修改: 以下也没有改善性能:
inline __host__ __device__ float dot(float4 a, float4 b)
{
a *= b;
return (a.x + a.y) + (a.z + a.w);
}
差异很明显:
time for cuda glm (dot): 223 milliseconds
time for cuda helper math (dot): 307 milliseconds
我使用以下内核进行测试(类似于glm,numElements 2000000,innerLoopSize 100)和std :: chrono :: high_resolution_clock进行测量。
__global__ void cuDotKernel(const float4 *vectors, float4 *result, int numElements, int innerLoopSize) {
int i = blockDim.x * blockIdx.x + threadIdx.x;
if(i < numElements) {
result[i] = vectors[i];
if(i>1 && i < NUM_ELEMENTS - 1) {
for(int j=0; j<innerLoopSize; j++) {
result[i].y = dot(vectors[i+1], vectors[i]);
result[i].x = dot(vectors[i-1], vectors[i]);
result[i].z = dot(vectors[i+1], result[i]);
result[i].w = dot(vectors[i-1], result[i]);
}
}
}
}
完整的测试代码位于bitbucket (the repo is public),it's possible to download directly (without hg)。
我测试了Linux,CUDA 6.5,GeForce gtx 550ti和glm 0.9.5.4
现在的问题是,为什么glm的实现速度更快?我怎样才能提高helper_maths的代码速度呢?
答案 0 :(得分:2)
我以矢量不“爆炸”的方式更改了测试数据。意味着它们保持在合理的范围内[0.0 - 1000.0]。现在时间非常相似。
似乎cuda编译器能够在glm的情况下优化一些计算,但在helper_math的情况下不能。