GPU代码数组元素总和的“-Nan”值
"-Nan" value for the total sum of array elements with GPU code
我正在编写计算数组元素总和的 OpenCL 代码。对于 1D 输入数组,每个尺寸在 1.024 * 1e+8 时都可以正常工作,但对于 1.024 * 1e+9,最终值为“-Nan”。
这是 this link
上的代码源
内核代码在 this link
上的 Makefile
这是最后一个有效的数组大小的结果(最后一个有效的大小值为 1.024 * 1e+8):
$ ./sumReductionGPU 102400000
Max WorkGroup size = 4100
Number of WorkGroups = 800000
Problem size = 102400000
Final Sum Sequential = 5.2428800512000000000e+15
Final Sum GPU = 5.2428800512000000000e+15
Initializing Arrays : Wall Clock = 0 second 673785 micro
Preparing GPU/OpenCL : Wall Clock = 1 second 925451 micro
Time for one NDRangeKernel call and WorkGroups final Sum : Wall Clock = 0 second 30511 micro
Time for Sequential Sum computing : Wall Clock = 0 second 398485 micro
我选了 local_item_size = 128
,所以如上所示,我选 800000 Work-Groups
NWorkItems = 1.024 * 1e+8
。
现在,如果我取 1.024 * 10^9,则不再计算部分和,我得到数组元素总和的“-nan”值。
$ ./sumReductionGPU 1024000000
Max WorkGroup size = 4100
Number of WorkGroups = 8000000
Problem size = 1024000000
Final Sum Sequential = 5.2428800006710899200e+17
Final Sum GPU = -nan
Initializing Arrays : Wall Clock = 24 second 360088 micro
Preparing GPU/OpenCL : Wall Clock = 19 second 494640 micro
Time for one NDRangeKernel call and WorkGroups final Sum : Wall Clock = 0 second 481910 micro
Time for Sequential Sum computing : Wall Clock = 166 second 214384 micro
也许我已经达到了 GPU 单元可以计算的极限。但我想得到你的建议来确认这一点。
如果 double
是 8 bytes
,这将需要 1.024 * 1e9 * 8 ~ 8 GBytes 用于输入数组:是不是太多了?我只有 8 GBytes 的 RAM。
根据您的经验,这个问题可能来自哪里?
谢谢
如您所知,一维输入数组需要大量内存。因此,malloc
或clCreateBuffer
的内存分配很容易失败。
对于 malloc
,我建议使用辅助函数 checked_malloc
,它会检测内存分配失败,打印出一条消息并退出程序。
#include <stdlib.h>
#include <stdio.h>
void * checked_malloc(size_t size, const char purpose[]) {
void *result = malloc(size);
if(result == NULL) {
fprintf(stderr, "ERROR: malloc failed for %s\n", purpose);
exit(1);
}
return result;
}
int main()
{
double *p1 = checked_malloc(1e8 * sizeof *p1, "array1");
double *p2 = checked_malloc(64 * 1e9 * sizeof *p2, "array2");
return 0;
}
在我只有 48 GB 虚拟内存的 PC 上,第二次分配失败,程序打印:
ERROR: malloc failed for array2
您也可以将此方案应用于 clCreateBuffer
。但是,无论如何您都必须检查每个 OpenCL 调用的结果。因此,我建议为此使用宏:
#define CHECK_CL_ERROR(result) if(result != CL_SUCCESS) { \
fprintf(stderr, "OpenCL call failed at: %s:%d with code %d\n", __FILE__, __LINE__, result); }
示例用法为:
cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY,
nWorkItems * sizeof(double), NULL, &ret);
CHECK_CL_ERROR(ret);
我正在编写计算数组元素总和的 OpenCL 代码。对于 1D 输入数组,每个尺寸在 1.024 * 1e+8 时都可以正常工作,但对于 1.024 * 1e+9,最终值为“-Nan”。
这是 this link
上的代码源内核代码在 this link
上的 Makefile这是最后一个有效的数组大小的结果(最后一个有效的大小值为 1.024 * 1e+8):
$ ./sumReductionGPU 102400000
Max WorkGroup size = 4100
Number of WorkGroups = 800000
Problem size = 102400000
Final Sum Sequential = 5.2428800512000000000e+15
Final Sum GPU = 5.2428800512000000000e+15
Initializing Arrays : Wall Clock = 0 second 673785 micro
Preparing GPU/OpenCL : Wall Clock = 1 second 925451 micro
Time for one NDRangeKernel call and WorkGroups final Sum : Wall Clock = 0 second 30511 micro
Time for Sequential Sum computing : Wall Clock = 0 second 398485 micro
我选了 local_item_size = 128
,所以如上所示,我选 800000 Work-Groups
NWorkItems = 1.024 * 1e+8
。
现在,如果我取 1.024 * 10^9,则不再计算部分和,我得到数组元素总和的“-nan”值。
$ ./sumReductionGPU 1024000000
Max WorkGroup size = 4100
Number of WorkGroups = 8000000
Problem size = 1024000000
Final Sum Sequential = 5.2428800006710899200e+17
Final Sum GPU = -nan
Initializing Arrays : Wall Clock = 24 second 360088 micro
Preparing GPU/OpenCL : Wall Clock = 19 second 494640 micro
Time for one NDRangeKernel call and WorkGroups final Sum : Wall Clock = 0 second 481910 micro
Time for Sequential Sum computing : Wall Clock = 166 second 214384 micro
也许我已经达到了 GPU 单元可以计算的极限。但我想得到你的建议来确认这一点。
如果 double
是 8 bytes
,这将需要 1.024 * 1e9 * 8 ~ 8 GBytes 用于输入数组:是不是太多了?我只有 8 GBytes 的 RAM。
根据您的经验,这个问题可能来自哪里?
谢谢
如您所知,一维输入数组需要大量内存。因此,malloc
或clCreateBuffer
的内存分配很容易失败。
对于 malloc
,我建议使用辅助函数 checked_malloc
,它会检测内存分配失败,打印出一条消息并退出程序。
#include <stdlib.h>
#include <stdio.h>
void * checked_malloc(size_t size, const char purpose[]) {
void *result = malloc(size);
if(result == NULL) {
fprintf(stderr, "ERROR: malloc failed for %s\n", purpose);
exit(1);
}
return result;
}
int main()
{
double *p1 = checked_malloc(1e8 * sizeof *p1, "array1");
double *p2 = checked_malloc(64 * 1e9 * sizeof *p2, "array2");
return 0;
}
在我只有 48 GB 虚拟内存的 PC 上,第二次分配失败,程序打印:
ERROR: malloc failed for array2
您也可以将此方案应用于 clCreateBuffer
。但是,无论如何您都必须检查每个 OpenCL 调用的结果。因此,我建议为此使用宏:
#define CHECK_CL_ERROR(result) if(result != CL_SUCCESS) { \
fprintf(stderr, "OpenCL call failed at: %s:%d with code %d\n", __FILE__, __LINE__, result); }
示例用法为:
cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY,
nWorkItems * sizeof(double), NULL, &ret);
CHECK_CL_ERROR(ret);