我想通过将值传递给来自命令行参数的内核来使Cuda应用程序更具动态性。Cuda传递值更快?
该应用程序调用多个内核,并最大化块和网格大小。当我尝试运行应用程序,这些都是结果我得到:
- 硬编码值:0.96秒
- 在内核初始化传递一个值:3.48秒
- 声明一个
__device__ int
,并将其设置为值:3.48秒
一旦在执行时输入值,它将在程序的其余部分保持不变。
这两个3.48秒来自访问变量本身。如果我要用一个硬编码的整数替换变量,则运行时会大幅度减少。这个值非常频繁地访问,我想知道是否有办法保持与硬编码值类似的速度,但是降低访问变量的成本。是否可以通过使用变量来加速?
3.6x慢些重要吗?有点。这只是一小部分更大的东西。
任何帮助将不胜感激。
*运行2.0硬件。
编辑:这是我遇到的不同的例子:./test 12
(12套X变量)
注的注释:与nvcc -m64 -gencode arch=compute_20,code=sm_20 -o test test.cu
运行:编译时
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <ctime>
using namespace std;
clock_t start;
__device__ int x;
__global__ void setNum(int i)
{
x = i;
return;
}
__device__ void d_swap(int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
__device__ void other(int n, int * vec)
{
int i;
for(i = 0; i < n; ++i) vec[i] = i;
for (int j = 0; j < 5; j++)
for(i = 1; i < n-1; ++i)
d_swap(&vec[i], &vec[i-1]);
}
__global__ void Pressure(int i)
{
int a[12];
other(x, a);
//other(12,a);
}
int main(int argc, char * argv[])
{
if (argc != 2)
{
fprintf(stderr,"Invalid number of arguments.\n");
exit(1);
}
int num = atoi(argv[1]);
cudaSetDevice(1);
cudaMemset(&x, num, sizeof(int));
setNum<<< 1 , 1>>>(num);
cudaError_t cuda_status = cudaDeviceSynchronize();
if (cuda_status != cudaSuccess) {
printf("No dice\n");
exit(1);
}
int results = 0;
cudaMemcpyFromSymbol(&results, x, sizeof(int));
printf("Value of x: %i\n", results);
start = clock();
for (int i = 0; i < 8; i++)
Pressure<<<65535, 1024>>>(i);
cuda_status = cudaDeviceSynchronize();
printf("Result: %f\n", (float)(clock()-start)/CLOCKS_PER_SEC);
return 0;
}
out代码块:
正在运行other(x, a);
,我得到1.370000
运行other(12,a);
,我得到0.020000
内核没有副作用,所以当常量被硬编码时,编译器能够确定没有操作并消除内核的整个主体。当x通过模块设备变量传递时,编译器不会完全优化内核。如果该常量的范围很小,那么可以使用函数模板专门化轻松实现此操作,并使用跳转表启动内核。如果常量的动态范围很大,那么您可能需要编写内核源代码模板,使用字符串替换来更新值,并在运行时对内核进行JIT。 –
@GregSmith感谢Greg,这真的很有帮助。 –