加速创意——CUDA能帮上忙吗?

加速创意——CUDA能帮上忙吗?,cuda,Cuda,我正在研究一个算法,它需要做一个小数字 对大量小型阵列执行的操作,有些是独立的 给出一个想法: 1k长度数组排序,通常为0.5k-1k元素 秩为10-20的矩阵的1k LU解 一切都在浮动中 然后,这个问题有一些横向性:上面 操作必须在10k阵列上独立进行 此外,中间结果不需要存储:例如,我不需要 需要保留已排序的数组,仅保留最小的$m$元素的总和 整个事情都用C++编程和运行。我的问题是: 你会认为这样的问题会得到显著的加速吗 (系数2或更多)使用CUDA?如果您“仅”需要系数2的加速,我

我正在研究一个算法,它需要做一个小数字 对大量小型阵列执行的操作,有些是独立的

给出一个想法:

  • 1k长度数组排序,通常为0.5k-1k元素
  • 秩为10-20的矩阵的1k LU解
一切都在浮动中

然后,这个问题有一些横向性:上面 操作必须在10k阵列上独立进行

此外,中间结果不需要存储:例如,我不需要 需要保留已排序的数组,仅保留最小的$m$元素的总和

整个事情都用C++编程和运行。我的问题是: 你会认为这样的问题会得到显著的加速吗 (系数2或更多)使用CUDA?

如果您“仅”需要系数2的加速,我建议在考虑GPGPU/CUDA之前,首先考虑更直接的优化可能性。例如,假设x86使用SSE,通过重新编写代码的性能关键部分以使用4路浮点SIMD,可以将速度提高4倍。虽然这将使您与x86绑定,但它的可移植性更强,因为它不需要nVidia GPU

话虽如此,您的代码库中甚至可能有更简单的优化机会,例如消除冗余操作(无用的拷贝和初始化是首选)或使内存访问模式更便于缓存。试着用一个合适的分析器分析代码,看看瓶颈在哪里

但是,请注意,通常情况下,排序并不特别适合SIMD或CUDA,但其他操作(如LU分解)可能会受益。

如果“仅”需要2倍的加速,我建议在考虑GPGPU/CUDA之前,首先考虑更直接的优化可能性。例如,假设x86使用SSE,通过重新编写代码的性能关键部分以使用4路浮点SIMD,可以将速度提高4倍。虽然这将使您与x86绑定,但它的可移植性更强,因为它不需要nVidia GPU

话虽如此,您的代码库中甚至可能有更简单的优化机会,例如消除冗余操作(无用的拷贝和初始化是首选)或使内存访问模式更便于缓存。试着用一个合适的分析器分析代码,看看瓶颈在哪里


但是,请注意,通常情况下,排序并不特别适合SIMD或CUDA,但其他操作(如LU分解)可能会受益。

仅几个指针,您可能已经合并了:

1) 如果您只需要m个最小的元素,您最好只搜索最小的元素,删除它并重复m次

2) 您是否已经在cpu上并行化了代码?OpenMP左右

3) 你想过买更好的硬件吗?(我知道这不是一个好主意,但如果你想达到某个特定应用程序的性能目标,它有时是最便宜的可能性…)

如果你想在CUDA上实现它,它应该在概念上起作用,所以不会出现大问题。然而,总有一些小事情,这取决于经验等等


考虑一下用于排序的推力库,希望其他人可以建议一些好的LU分解算法。

仅几个指针,您可能已经合并了:

1) 如果您只需要m个最小的元素,您最好只搜索最小的元素,删除它并重复m次

2) 您是否已经在cpu上并行化了代码?OpenMP左右

3) 你想过买更好的硬件吗?(我知道这不是一个好主意,但如果你想达到某个特定应用程序的性能目标,它有时是最便宜的可能性…)

如果你想在CUDA上实现它,它应该在概念上起作用,所以不会出现大问题。然而,总有一些小事情,这取决于经验等等


考虑一下用于排序的推力库,希望其他人能推荐一些好的LU分解算法。

您可以在5行代码中运行它。通过CPU,我得到了~6倍的加速。我得到了~4X的加速比和这个超推力(它是为向量而不是矩阵设计的)。因为您只使用一个GPU,所以可以运行ArrayFire免费版本

array x = randu(512,1000,f32);
array y = sort(x); // sort each 512-element column independently
array x = randu(15,15,1000,f32), y;
gfor (array i, x.dim(2))
  y(span,span,i) = lu(x(span,span,i)); // LU-decomposition of each 15x15 matrix

请记住,当内存访问与32的倍数对齐时,GPU的性能最佳,因此一组32x32矩阵的性能将优于一组31x31矩阵。

您可以在5行代码中运行此操作。通过CPU,我得到了~6倍的加速。我得到了~4X的加速比和这个超推力(它是为向量而不是矩阵设计的)。因为您只使用一个GPU,所以可以运行ArrayFire免费版本

array x = randu(512,1000,f32);
array y = sort(x); // sort each 512-element column independently
array x = randu(15,15,1000,f32), y;
gfor (array i, x.dim(2))
  y(span,span,i) = lu(x(span,span,i)); // LU-decomposition of each 15x15 matrix

请记住,当内存访问以32的倍数对齐时,GPU的性能最好,因此一组32x32矩阵的性能将优于一组31x31矩阵。

花费的绝大多数时间都在stl排序和eigen LU分解的子代中。由于该任务重复性很强,因此很少进行初始化/复制。该代码已在启用SSE和AVX标志的情况下编译。在这一点上,可移植性是次要考虑的问题。感谢指向4路SIMD的指针——尽管我相信这已经由Egen处理。请注意,使用SSE/AVX标志编译并不一定会生成任何SIMD代码(一些编译器,如ICC和带有适当开关的较新版本的gcc,可以执行一些基本的自动矢量化,但它非常有限)。另外请注意,AVX不支持8路浮点SIMD,因此,如果您可以假设一个支持AVX的CPU,那么可能存在一些8路SIMD优化机会,这些机会目前未被th利用