| 1041 | } |
| 1042 | |
| 1043 | void host_kernel::execute_device(const host_kernel_entry& func_entry, |
| 1044 | const uint32_t& cpu_count, |
| 1045 | const uint3& group_dim, |
| 1046 | const uint3& local_dim, |
| 1047 | const uint32_t& work_dim, |
| 1048 | const vector<const void*>& vptr_args) const { |
| 1049 | // #work-groups |
| 1050 | const auto group_count = group_dim.x * group_dim.y * group_dim.z; |
| 1051 | // #work-items per group |
| 1052 | const uint32_t local_size = local_dim.x * local_dim.y * local_dim.z; |
| 1053 | // group ticketing system, each worker thread will grab a new group id, once it's done with one group |
| 1054 | atomic<uint32_t> group_idx { 0 }; |
| 1055 | |
| 1056 | // start worker threads |
| 1057 | #if defined(FLOOR_HOST_KERNEL_ENABLE_TIMING) |
| 1058 | const auto time_start = floor_timer::start(); |
| 1059 | #endif |
| 1060 | atomic<bool> success { true }; |
| 1061 | vector<unique_ptr<thread>> worker_threads(cpu_count); |
| 1062 | for (uint32_t cpu_idx = 0; cpu_idx < cpu_count; ++cpu_idx) { |
| 1063 | worker_threads[cpu_idx] = make_unique<thread>([this, &success, cpu_idx, &func_entry, &vptr_args, |
| 1064 | &group_idx, group_count, group_dim, |
| 1065 | local_size, local_dim, work_dim] { |
| 1066 | // set cpu affinity for this thread to a particular cpu to prevent this thread from being constantly moved/scheduled |
| 1067 | // on different cpus (starting at index 1, with 0 representing no affinity) |
| 1068 | core::set_thread_affinity(cpu_idx + 1); |
| 1069 | |
| 1070 | // retrieve the instance for this CPU + reset/init it |
| 1071 | auto instance = func_entry.program->get_instance(cpu_idx); |
| 1072 | if (!instance) { |
| 1073 | log_error("no instance for CPU #$ (for $)", cpu_idx, func_name); |
| 1074 | success = false; |
| 1075 | return; |
| 1076 | } |
| 1077 | instance->reset(local_dim * group_dim, local_dim, group_dim, work_dim); |
| 1078 | |
| 1079 | auto& exec_ctx = device_exec_context; |
| 1080 | exec_ctx.ids = &instance->ids; |
| 1081 | exec_ctx.linear_local_work_size = local_size; |
| 1082 | auto& ids = instance->ids; |
| 1083 | |
| 1084 | // get and set the (kernel) function for this instance |
| 1085 | const auto& func_info = *func_entry.info; |
| 1086 | const auto func_iter = instance->functions.find(func_info.name); |
| 1087 | if (func_iter == instance->functions.end()) { |
| 1088 | log_error("failed to find function \"$\" for CPU #$", func_name, cpu_idx); |
| 1089 | success = false; |
| 1090 | return; |
| 1091 | } |
| 1092 | exec_ctx.kernel_func = make_callable_kernel_function(func_iter->second, vptr_args); |
| 1093 | if (!exec_ctx.kernel_func) { |
| 1094 | log_error("failed to create kernel function \"$\" for CPU #$", func_name, cpu_idx); |
| 1095 | success = false; |
| 1096 | return; |
| 1097 | } |
| 1098 | |
| 1099 | // init contexts (aka fibers) |
| 1100 | floor_fiber_context main_ctx; |
nothing calls this directly
no test coverage detected