OpenCl 无法使用 'printf' 编译内核

OpenCl cannot compile kernel with 'printf'

我在尝试构建 OpenCL 内核时遇到错误 error: implicit declaration of function 'printf' is invalid in OpenCL。内核代码是这样

__kernel void conj_grad(int dim, int num_vals, __local float *r,                
      __local float *x, __local float* A_times_p, __local float *p,             
      __global int *rows, __global int *cols, __global float *A,                
      __global float *b, __global float *result) {                              
                                                                                
   local float alpha, r_length, old_r_dot_r, new_r_dot_r;                       
   local int iteration;                                                         
                                                                                
   int id = get_local_id(0);                                                    
   int start_index = -1;                                                        
   int end_index = -1;                                                          
   float Ap_dot_p;                                                              
                                                                                
   printf("OpenCL Kernel ID: %d\n", id);   

这给了我下面的错误

input.cl:14:4: error: implicit declaration of function 'printf' is invalid in OpenCL
input.cl:14:4: note: did you mean 'rint'?
/usr/include/clc/math/unary_decl.inc:1:39: note: 'rint' declared here
/usr/include/clc/math/rint.h:2:24: note: expanded from macro '__CLC_FUNCTION'
input.cl:46:45: warning: double precision constant requires cl_khr_fp64, casting to single precision

我从这个函数中得到一个否定的 return 代码 err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);

我已经尝试了这些问题的解决方案Using printf() in OpenCL kernel and printf function doesn't work in OpenCL kernel,但这些解决方案都没有解决它。当我尝试这些解决方案时,我看到一条警告,例如 input.cl:1:26: warning: unknown OpenCL extension 'cl_amd_printf' - ignoring

结论

看来我的系统不支持 printf 扩展。下面的代码(从 pmdj 的答案中窃取)为我提供了以下输出。看起来像一个经典的故事,不依赖于供应商特定的标准扩展。

#include <stdio.h>                                                              
#include <CL/cl.h>                                                              
                                                                                
int main(void) {                                                                
    char ext_str[1024] = "";                                                    
    size_t ext_str_len = sizeof(ext_str) - 1;                                   
    cl_device_id device_id;                                                     
    cl_int err;                                                                 
    cl_platform_id platform;                                                    
                                                                                
    err = clGetPlatformIDs(1, &platform, NULL);                                 
    if(err < 0) {                                                               
        perror("Couldn't identify a platform");                                 
        exit(1);                                                                
    }                                                                           
                                                                                
    err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);       
    if(err < 0) {                                                               
        perror("Couldn't access any devices");                                  
        exit(1);                                                                
    }                                                                           
                                                                                
    err = clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, sizeof(ext_str), ext_str, &ext_str_len);
    if(err < 0) {                                                               
        perror("Couldn't get device info");                                     
        exit(1);                                                                
    }                                                                           
                                                                                
    printf("CL extensions (%lu): '%s'\n", ext_str_len, ext_str);                
    return 0;                                                                   
} 
CL extensions (248): 'cl_khr_byte_addressable_store cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_fp64 cl_khr_fp16'

如您所见,printf 不是标准 OpenCL 的一部分,但一些实现提供了支持它的扩展。

要检查您的实施支持的扩展,请尝试如下操作:

char ext_str[1024] = "";
size_t ext_str_len = sizeof(ext_str) - 1;
err = clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, sizeof(ext_str), ext_str, &ext_str_len);
printf("CL extensions (%lu): '%s'\n", ext_str_len, ext_str);

如果没有列出任何 cl_*_printf 扩展程序,您可能运气不好。如果列出了一个,您需要按照您链接的其他答案中的描述启用它。您可能还想检查您所支持的特定扩展的规范,以防它表现出任何特殊的怪癖。