| 48 | } |
| 49 | |
| 50 | cuda_program::cuda_program(program_map_type&& programs_) : |
| 51 | device_program(retrieve_unique_function_names(programs_)), programs(std::move(programs_)) { |
| 52 | if (programs.empty()) { |
| 53 | return; |
| 54 | } |
| 55 | |
| 56 | #if 0 // for debugging/testing purposes |
| 57 | for (auto&& prog : programs) { |
| 58 | uint32_t func_count = 0u; |
| 59 | CU_CALL_CONT(cu_module_get_function_count(&func_count, prog.second.program), |
| 60 | "failed to retrieve function count") |
| 61 | std::vector<cu_function> funcs(func_count, nullptr); |
| 62 | CU_CALL_CONT(cu_module_enumerate_functions(funcs.data(), func_count, prog.second.program), |
| 63 | "failed to enumerate functions") |
| 64 | log_msg("CUDA module: expected $' functions, got $'", prog.second.functions.size(), func_count); |
| 65 | for (auto& func : funcs) { |
| 66 | const char* func_name = nullptr; |
| 67 | CU_CALL_CONT(cu_func_get_name(&func_name, func), "failed to query function name") |
| 68 | log_msg("CUDA function: loading \"$\" ...", func_name ? func_name : "<invalid-func-name>"); |
| 69 | CU_CALL_CONT(cu_func_load(func), "function load finalize failed") |
| 70 | } |
| 71 | } |
| 72 | #endif |
| 73 | |
| 74 | // create all functions of all device programs |
| 75 | // note that this essentially reshuffles the program "device -> functions" data to "functions -> devices" |
| 76 | functions.reserve(function_names.size()); |
| 77 | for (const auto& function_name : function_names) { |
| 78 | cuda_function::function_map_type function_map; |
| 79 | for (auto&& prog : programs) { |
| 80 | if (!prog.second.valid) continue; |
| 81 | for (const auto& info : prog.second.functions) { |
| 82 | if (info.name == function_name) { |
| 83 | if (should_ignore_function_for_device(*prog.first, info)) { |
| 84 | continue; |
| 85 | } |
| 86 | |
| 87 | cuda_function::cuda_function_entry entry; |
| 88 | entry.info = &info; |
| 89 | entry.function_args_size = device_function_args_size(info); |
| 90 | entry.max_local_size = prog.first->max_local_size; |
| 91 | |
| 92 | CU_CALL_CONT(cu_module_get_function(&entry.function, prog.second.program, function_name.c_str()), |
| 93 | "failed to get function \"" + function_name + "\"") |
| 94 | |
| 95 | // retrieve max local work size for this kernel for this device |
| 96 | int max_total_local_size = 0; |
| 97 | CU_CALL_IGNORE(cu_function_get_attribute(&max_total_local_size, |
| 98 | CU_FUNCTION_ATTRIBUTE::MAX_THREADS_PER_BLOCK, entry.function)) |
| 99 | entry.max_total_local_size = (max_total_local_size < 0 ? 0 : (uint32_t)max_total_local_size); |
| 100 | if (info.has_valid_required_local_size()) { |
| 101 | // check and update local size if a required local size was specified |
| 102 | const auto req_local_size = info.required_local_size.maxed(1u).extent(); |
| 103 | if (req_local_size > entry.max_total_local_size) { |
| 104 | log_error("in kernel $: supported total local size $' is < required total local size $' ($)", |
| 105 | function_name, entry.max_total_local_size, req_local_size, info.required_local_size); |
| 106 | continue; |
| 107 | } |
nothing calls this directly
no test coverage detected