Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
Performance 两个几乎相同的OpenCL内核之间的性能差距_Performance_Opencl_Gpu_Flops - Fatal编程技术网

Performance 两个几乎相同的OpenCL内核之间的性能差距

Performance 两个几乎相同的OpenCL内核之间的性能差距,performance,opencl,gpu,flops,Performance,Opencl,Gpu,Flops,我有两个几乎相同的OpenCL内核,我想用GFLOPS计算它们的性能。内核1是: __kernel void Test41(__global float *data, __global float *rands, int index, int rand_max){ float16 temp; int gid = get_global_id(0); temp = data[gid]; temp = (float) rands[1] * temp; tem

我有两个几乎相同的OpenCL内核,我想用GFLOPS计算它们的性能。内核1是:

__kernel void Test41(__global float *data, __global float *rands, int index, int rand_max){

    float16 temp;
    int gid = get_global_id(0);

    temp = data[gid];
    temp = (float) rands[1] * temp;
    temp = (float) rands[2] * temp;
    temp = (float) rands[3] * temp;
    temp = (float) rands[4] * temp;
    .
    .
    .
    temp = (float) rands[497] * temp;
    temp = (float) rands[498] * temp;
    temp = (float) rands[499] * temp;
    data[gid] = temp.s0;

}
第二个内核是:

__kernel void Test42(__global float *data, __global float *rands, int index, int rand_max){

    float16 temp[500];
    int gid = get_global_id(0);

    temp[0] = data[gid];
    temp[1] = (float) rands[1] * temp[0];
    temp[2] = (float) rands[2] * temp[1];
    temp[3] = (float) rands[3] * temp[2];
    temp[4] = (float) rands[4] * temp[3];
    .
    .
    .
    temp[497] = (float) rands[497] * temp[496];
    temp[498] = (float) rands[498] * temp[497];
    temp[499] = (float) rands[499] * temp[498];
    data[gid] = temp[index].s0;

}
正如您在代码中看到的,我使用的流大小为16。每个内核有500行操作,其中每个操作只执行一个浮点操作。我还总共部署了大约1048576个内核,因此我将有大约1048576个并行执行的工作项

为了计算触发器,我执行以下操作:

flops = #numWorkItems(1048576) * (500) * StreamSize(16) / timeTaken;
不幸的是,对于第一个内核,我得到了大约1.4tflops,但是对于第二个内核,我得到了38gflops。我无法解释这个巨大的差距。使用temp向量而不是单个temp似乎是一件大事。看起来真正的应用程序大多类似于第二个内核。第一个内核对于真正的应用程序来说太简单了

有谁能帮助我理解这里到底发生了什么,以及第二个内核性能如何达到第一个内核性能?一般来说,如果我要对我的设备进行基准测试,我应该期望看到性能接近理论值吗


另外,我知道我需要将rands复制到一个本地内存中,但现在让我们跳过它。

有两个可能的问题:

您将float16 temp buffer声明为uuu private{,这是OpenCL}中的默认值,很可能它将分配到具有相当高访问延迟的全局内存空间中。如果它适合您的设备本地内存,您可以尝试将其声明为_local float16。 添加临时缓冲区给编译器带来了一些问题。。。原始代码很容易在某些GPU架构上矢量化,例如Intel,您通过添加store+load添加了人工依赖项
我会提交一份关于编译器的问题报告。编译器应该很容易找出依赖项,进行优化,甚至去掉临时缓冲区。

正如@pmdj在评论中所建议的,第二个内核的主要问题是寄存器压力:您使用了大量硬件寄存器,这减少了同时执行的工作组的数量。 一般来说,在OpenCL/CUDA中,大型私有阵列不是一个好主意。 在这种情况下,编译器几乎无法优化性能。
您可以为阵列使用本地内存,但随后需要添加适当的同步来访问它。

在第二个内核中,为500个浮点16值的阵列分配了大量寄存器,因此,很可能内核占用率降低,导致内核运行缓慢。对于单个线程,500*16*4=32kB。由于内存的使用,即使是每个工作组的单个工作项也会很慢。每个工作项的合理内存使用量是多少?我只是想在设计我的基准测试时更好地掌握。请查看各种硬件供应商的OpenCL优化指南。Nvidia、AMD和Intel都有它们,让您了解如何估计其设备的占用率。移动设备供应商可能会提供类似的文档。通常情况下,每个CU都有固定数量的寄存器,如果将其除以一个线程使用的寄存器数量,则会得到可以同时在CU上运行的线程数量的上限。Hi。我对代码做了一些更改,因此我将分配10个临时数组,而不是分配一个大小为500的本地临时数组,然后在内核中的所有500条语句中以循环方式使用这些临时数组。但我还是得到了同样的业绩数字。这是什么原因?谢谢你,伊拉尔。关于你的评论,我有一些问题:1你说我分配的_私有内存很可能分配在全局内存空间中。原因是什么?2我之所以添加依赖项,是因为我希望我的基准测试能够做到这一点。基本上,我希望每个内核的内容都与数据相关。就我的内核而言,编译器如何进一步优化它?@saman 1 OpenCL spec 2我看不出有任何具体的理由这样做,而是为了弄清楚OpenCL编译器有多好,它看起来很糟糕。嗨,Elal。我正在查看OpenCL规范表,但我无法准确地检测到在全局内存中可以分配私有内存的位置。你能提到哪个页面包含这些信息吗?我基本上已经将临时数组的大小从500减少到了10,但内核的大小保持不变。仍然看不到性能数字的任何差异。看起来第二个内核中的某些东西给GPU加速带来了很大的问题。你有没有使用一些分析器工具?它可能会给你一些关于寄存器溢出的信息。10个元素的float16数组对您的硬件来说可能还是太多了。我明白了。你知道我可以为Nvidia Tesla GPU使用的OpenCL分析器吗?似乎nvidia smi不再支持OpenCL了。