如何无需将cpu_kernel_trainMe设为静态即可赋值给StarPU的cpu_funcs
问题解决方法
报错根因
非静态类成员函数默认携带隐式this指针入参,因此它的函数签名void (StarPuNet::)(void**, void*)和StarPU要求的无类上下文的普通函数指针starpu_cpu_func_t(即void (*)(void**, void*))类型不匹配,直接赋值会触发类型转换错误。你之前尝试的强制类型转换写法本身语法错误,且即便语法正确也无法解决隐式this的传参问题,运行时会触发内存访问异常。
可行方案(无需修改cpu_kernel_trainMe为静态)
利用StarPU回调的cl_arg参数透传当前类实例指针,新增一个静态转发入口即可,原业务方法完全保留非静态属性。
方案1:单独声明静态代理函数
修改后的代码如下:
class StarPuNet { public: // 原方法保持非静态,无需任何修改 void cpu_kernel_trainMe(void *buffers[], void *cl_arg) {} // 新增静态代理函数,仅做转发逻辑 static void cpu_kernel_proxy(void *buffers[], void *cl_arg) { StarPuNet* instance = static_cast<StarPuNet*>(cl_arg); instance->cpu_kernel_trainMe(buffers, cl_arg); } int initStarPu() { starpu_codelet_init(&cl_); // 此处赋值代理函数即可 cl_.cpu_funcs[0] = cpu_kernel_proxy; cl_.cpu_funcs_name[0] = "cpu_kernel_trainMe"; cl_.nbuffers = 3; cl_.modes[0] = STARPU_R; cl_.modes[1] = STARPU_R; cl_.modes[2] = STARPU_W; cl_.name = "trainMe"; return 0; }; // 提交任务时需要将当前实例指针传入cl_arg参数,示例如下: // starpu_task_insert(&cl_, // STARPU_R, buf1, // STARPU_R, buf2, // STARPU_W, buf3, // STARPU_CL_ARGS, this, sizeof(this), // 0); private: starpu_codelet cl_; };
方案2:C++11+ 用无捕获lambda简化代码
无需单独声明静态代理函数,直接在赋值处写无捕获lambda即可,无捕获lambda可以隐式转换为普通函数指针:
int initStarPu() { starpu_codelet_init(&cl_); cl_.cpu_funcs[0] = [](void *buffers[], void *cl_arg) { static_cast<StarPuNet*>(cl_arg)->cpu_kernel_trainMe(buffers, cl_arg); }; cl_.cpu_funcs_name[0] = "cpu_kernel_trainMe"; cl_.nbuffers = 3; cl_.modes[0] = STARPU_R; cl_.modes[1] = STARPU_R; cl_.modes[2] = STARPU_W; cl_.name = "trainMe"; return 0; };
内容的提问来源于stack exchange,提问作者Awesome JSF
相关产品推荐
相关产品推荐

