Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenCL优化_Opencl - Fatal编程技术网

OpenCL优化

OpenCL优化,opencl,Opencl,我是OpenCL的新手。 我写了一个OpenCL内核来计算灰度。我如何优化代码,这是可能的?为什么计算时间浮动这么多?有时我会加快别人的速度。我做错了什么 kernel code: kernel void grayscale(__global unsigned char *input) { size_t i = get_global_id(0); float grayscaleValue = (input[i*3] * 0.299F) + (input[i*3+1] *

我是OpenCL的新手。 我写了一个OpenCL内核来计算灰度。我如何优化代码,这是可能的?为什么计算时间浮动这么多?有时我会加快别人的速度。我做错了什么

kernel code:
kernel void grayscale(__global unsigned char *input)
{
    size_t i = get_global_id(0);    

    float grayscaleValue = (input[i*3] * 0.299F) + (input[i*3+1] * 0.587F) + (input[i*3+2] * 0.114F);

    input[i*3] = grayscaleValue;
    input[i*3+1] = grayscaleValue;
    input[i*3+2] = grayscaleValue;   
}


cpu code:
void GrayScaleCPU(struct PPMFile *ppmStruct)
{    
    for (int i = 0; i < ppmStruct->imageSize; i+=3)
    {
        float greyscaleValue = (ppmStruct->data[i] * 0.299F) + (ppmStruct->data[i+1] * 0.587F) + (ppmStruct->data[i+2] * 0.114F);
        ppmStruct->out[i] = greyscaleValue;
        ppmStruct->out[i+1] = greyscaleValue;
        ppmStruct->out[i+2] = greyscaleValue;
    }
}

int main(void)
{
    struct timespec tS1, tS2;

    tS1.tv_sec = 0;
    tS1.tv_nsec = 0;

    tS2.tv_sec = 0;
    tS2.tv_nsec = 0;

    ...

    clock_settime(CLOCK_REALTIME, &tS1);
    GrayScaleCPU(ppmf);
    clock_gettime(CLOCK_REALTIME, &tS1);

    printf ("Timming took %.12lu seconds to run.\n", tS1.tv_nsec);

    ...

    clock_settime(CLOCK_REALTIME, &tS2);
    GrayScaleOpenCL(ppmf2);
    clock_gettime(CLOCK_REALTIME, &tS2);

    printf ("Timming took %.12lu seconds to run.\n", tS2.tv_nsec);

    float time2 = tS2.tv_nsec;
    float time1 = tS1.tv_nsec;
    float speedup = time2/time1;

    printf ("Speed UP OpenCL/CPU %.20f.\n", speedup);
    return 0;
}
内核代码:
内核无效灰度(uu全局无符号字符*输入)
{
size\u t i=获取全局\u id(0);
浮点灰度值=(输入[i*3]*0.299F)+(输入[i*3+1]*0.587F)+(输入[i*3+2]*0.114F);
输入[i*3]=灰度值;
输入[i*3+1]=灰度值;
输入[i*3+2]=灰度值;
}
cpu代码:
void GrayScaleCPU(结构PPMFile*ppmStruct)
{    
对于(int i=0;iimageSize;i+=3)
{
浮动灰度标度值=(ppmStruct->data[i]*0.299F)+(ppmStruct->data[i+1]*0.587F)+(ppmStruct->data[i+2]*0.114F);
ppmStruct->out[i]=灰度标度值;
ppmStruct->out[i+1]=灰度标度值;
ppmStruct->out[i+2]=灰度标度值;
}
}
内部主(空)
{
结构timespec tS1、tS2;
tS1.tv_sec=0;
tS1.tv_nsec=0;
tS2.tv_sec=0;
tS2.tv_nsec=0;
...
时钟设置时间(时钟实时和tS1);
灰度ecpu(ppmf);
时钟获取时间(时钟实时,&tS1);
printf(“Timming运行时间为%.12lu秒。\n”,tS1.tv\u nsec);
...
时钟设置时间(时钟实时和tS2);
灰度图(ppmf2);
时钟获取时间(时钟实时,&tS2);
printf(“Timming运行时间为%.12lu秒。\n”,tS2.tv\u nsec);
浮动时间2=tS2.tv\u nsec;
浮动时间1=tS1.tv\u nsec;
浮动加速=时间2/时间1;
printf(“加速OpenCL/CPU%.20f.\n”,加速);
返回0;
}

尝试将全局内存缓冲到线程内存中:

unsigned char l_input0 = input[i*3];
unsigned char l_input1 = input[i*3 + 1];
unsigned char l_input2 = input[i*3 + 2];
//compute grayscale using l_input0,1,2
input[i*3] = grayscale;
input[i*3 + 1] = grayscale;
input[i*3 + 2] = grayscale;
此外,如果在调用内核时数据的间隔不正确,则可能会在每个无符号字符上执行,而不是像for循环中那样在第三个无符号字符上执行

然后,您可以进一步使用本地内存和工作组,并分块进行计算,尽管这更具挑战性,因为本地工作大小非常特定于设备,需要是全局工作大小的倍数。我发现16、32和64的本地工作大小适用于大多数设备


最后,对OpenCL进行基准测试,确保测量的是内核性能,而不是内核排队时间。最简单的方法是启动一个计时器,让内核排队,在队列上调用clainish,然后停止计时器。大多数OpenCL设备都内置了定时和评测功能,这些功能由队列处理。

您测量的是什么,如何测量?我测量的是这两个功能中的时间。在opencl的情况下,我会测量所有与准备内核午餐有关的事情。使用struct timespec。是吗@您正在测量创建命令队列、上下文和构建程序?如果你这样做是错误的,你也应该衡量执行情况大约十次,放弃第一次,因为它通常较慢,然后取平均值。是的,我衡量一切,不应该这样做吗?我应该只测量内核“clEnqueueNDRangeKernel”的执行情况?关于设备之间的内存传输,我也应该放弃吗?内存事务可以包括在内,但在现代GPU上,它们与计算并行进行(第二次迭代计算可以在第一次迭代数据读回的同时进行)。但是是的,你应该只测量内核执行时间和数据传输检查这个,还有一些其他问题也应该帮助你为什么我不应该测量排队时间?它属于过程,不是吗@当然,您可以测量它,但它是A)无关紧要的,B)仅仅因为内核排队并不意味着它就完成了,所以在收集计时数据时要小心。这就是警告。