-
Notifications
You must be signed in to change notification settings - Fork 0
Incorporate determinism into GPU heuristics + parallel determinsitic B&B+GPU exploration #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8cec498
a559d79
3269d87
20277f2
55126d9
58d9a42
6b9324c
db75bd6
7315ab8
24eb4ac
8cbc37a
7ee2c49
d5677fe
429c492
f6e1370
f02837a
773dbd4
327fcec
c9cae3c
575520f
017c4d5
8cb04ec
f5f2726
c4d3fde
6780893
7474ff0
c6e9d15
c24f6ef
c70bc1b
4e0f79a
bcadb92
66288f8
8e19de8
5eacbb8
b96a784
ccc64a2
01afc9d
6ba4905
3e6d081
38df1ec
c713dbc
3b0d116
380bb1d
7f81da1
2726d23
7ea0f1d
4e74f15
709f281
41198e2
d98e083
786ae8a
2fade1d
c89e2c9
cbfd34b
ea5e1bd
8c53c75
c6a1037
09a484a
f55e648
554d24c
db73e00
0b8b6e1
122bfbc
45ebd57
a209096
718f3e7
1df9313
b45982e
d272180
0987b5c
f378246
4b77a59
bcea60d
d7ff462
37ca39e
5c9e59a
22c95a7
0fc30c5
8bd70e3
7bcf3ba
4bfb96f
f1afa59
cd2595e
6a1192f
8dfdfd8
8f26067
24fdc75
759b896
dc30219
1ca01ba
5894ffe
9911c3a
24b828e
d52bcb0
ef69eb7
7ac230f
24d7ccb
d35bed2
1913946
ecf9f25
fb9c782
4a51ca7
1a4ac76
ce44aff
9b881d8
b293e94
88adfcd
ee7037f
fb0c072
e3f2a79
057ecc7
2463de6
8356f1d
192ce53
8b31229
3cced01
63c917a
d33939b
47ae4cf
ed224fb
741f373
63b9ed1
0ea2c1f
00326e2
c374f69
2ae3d3e
d89c50a
d67f230
eb6bc28
d80667c
8ed172a
2a16ee6
ef777c6
6dcb062
35e8177
e06af9f
99e9ec2
8fdbff8
b6d7ecc
668391e
3b6d532
81aaf20
07cea4d
9fb0edd
e5e498d
525c7b5
bb5ed1c
1dc32de
79a6d54
ec248cd
9579cd1
c8a9836
5e13486
ec5152a
0d70d96
2b0e5e4
21bf0a5
75c942a
9db457b
c3e7ff6
3ed12cf
1e5807b
2322ad1
e532bcd
f80c733
e3e37ad
4c9f494
8e9a2fc
c217922
90f184c
ec4239b
014dc72
58c6c4b
5e5d285
068c699
7d0fd31
e077cb4
0619554
4907783
cc10766
8cd14cc
6e1be5b
bc93781
e6b7457
0e9427f
295fd7e
92ccbe9
59e0ad0
0a47fe0
eaf45e6
02a5bf8
fff6a8e
d915f6a
0a0f12f
3a7b43f
6494275
588c77f
7613978
d423c6f
638d35f
e8bdc7c
41ac7bb
1867f30
a90233f
9598b37
83b78ef
0227513
18a2d4d
3e214a8
e8b1291
cc1e5c3
859975f
a63af82
894b200
0a20329
f7ebf56
479b662
27fb24b
9a4b1d0
e87c98f
73dffbe
472f2b6
8d4e34b
cc33495
1ef5fd9
e80e545
427b78c
b41dc3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |||||
| #include <cuopt/linear_programming/mip/solver_solution.hpp> | ||||||
| #include <cuopt/linear_programming/optimization_problem_interface.hpp> | ||||||
| #include <cuopt/linear_programming/solve.hpp> | ||||||
| #include <cuopt/linear_programming/utilities/internals.hpp> | ||||||
| #include <mps_parser/parser.hpp> | ||||||
| #include <utilities/logger.hpp> | ||||||
|
|
||||||
|
|
@@ -137,6 +138,58 @@ std::vector<std::vector<double>> read_solution_from_dir(const std::string file_p | |||||
| return initial_solutions; | ||||||
| } | ||||||
|
|
||||||
| struct incumbent_record_t { | ||||||
| double objective; | ||||||
| double work_timestamp; | ||||||
| double wall_time; | ||||||
| cuopt::internals::mip_solution_origin_t origin; | ||||||
| }; | ||||||
|
|
||||||
| class incumbent_tracker_t : public cuopt::internals::get_solution_callback_ext_t { | ||||||
| public: | ||||||
| incumbent_tracker_t(std::chrono::high_resolution_clock::time_point start_time) | ||||||
| : start_time_(start_time) | ||||||
| { | ||||||
| } | ||||||
|
|
||||||
| void get_solution(void* data, | ||||||
| void* cost, | ||||||
| void* solution_bound, | ||||||
| const cuopt::internals::mip_solution_callback_info_t* info, | ||||||
| void* user_data) override | ||||||
| { | ||||||
| double obj = *static_cast<double*>(cost); | ||||||
| double wt = (info != nullptr) ? info->work_timestamp : -1.0; | ||||||
| auto origin = | ||||||
| (info != nullptr) ? info->origin : cuopt::internals::mip_solution_origin_t::UNKNOWN; | ||||||
| auto now = std::chrono::high_resolution_clock::now(); | ||||||
| double wall_s = std::chrono::duration<double>(now - start_time_).count(); | ||||||
| records_.push_back({obj, wt, wall_s, origin}); | ||||||
| } | ||||||
|
|
||||||
| void write_csv(const std::string& path) const | ||||||
| { | ||||||
| std::ofstream f(path); | ||||||
| if (!f.is_open()) { | ||||||
| fprintf(stderr, "Failed to open incumbent CSV: %s\n", path.c_str()); | ||||||
| return; | ||||||
| } | ||||||
| f << "index,objective,work_timestamp,wall_time_s,origin\n"; | ||||||
| for (size_t i = 0; i < records_.size(); ++i) { | ||||||
| auto& r = records_[i]; | ||||||
| f << i << "," << std::setprecision(15) << r.objective << "," << r.work_timestamp << "," | ||||||
| << std::setprecision(6) << r.wall_time << "," | ||||||
| << cuopt::internals::mip_solution_origin_to_string(r.origin) << "\n"; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| size_t size() const { return records_.size(); } | ||||||
|
|
||||||
| private: | ||||||
| std::chrono::high_resolution_clock::time_point start_time_; | ||||||
| std::vector<incumbent_record_t> records_; | ||||||
| }; | ||||||
|
|
||||||
| int run_single_file(std::string file_path, | ||||||
| int device, | ||||||
| int batch_id, | ||||||
|
|
@@ -203,28 +256,47 @@ int run_single_file(std::string file_path, | |||||
| } | ||||||
| } | ||||||
| } | ||||||
| settings.time_limit = time_limit; | ||||||
| settings.work_limit = work_limit; | ||||||
| settings.heuristics_only = heuristics_only; | ||||||
| settings.num_cpu_threads = num_cpu_threads; | ||||||
| settings.log_to_console = log_to_console; | ||||||
| settings.determinism_mode = deterministic ? CUOPT_MODE_DETERMINISTIC : CUOPT_MODE_OPPORTUNISTIC; | ||||||
| settings.time_limit = time_limit; | ||||||
| settings.work_limit = work_limit; | ||||||
| settings.heuristics_only = heuristics_only; | ||||||
| settings.num_cpu_threads = num_cpu_threads; | ||||||
| settings.log_to_console = log_to_console; | ||||||
| if (deterministic) { | ||||||
| settings.determinism_mode = | ||||||
| heuristics_only ? CUOPT_MODE_DETERMINISTIC_GPU_HEURISTICS : CUOPT_MODE_DETERMINISTIC; | ||||||
| } else { | ||||||
| settings.determinism_mode = CUOPT_MODE_OPPORTUNISTIC; | ||||||
| } | ||||||
| CUOPT_LOG_INFO( | ||||||
| "1run_mip settings: heuristics_only=%d deterministic=%d determinism_mode=%d " | ||||||
| "time_limit=%.6f work_limit=%.6f", | ||||||
| (int)heuristics_only, | ||||||
| (int)deterministic, | ||||||
| settings.determinism_mode, | ||||||
| settings.time_limit, | ||||||
| settings.work_limit); | ||||||
| settings.tolerances.relative_tolerance = 1e-12; | ||||||
| settings.tolerances.absolute_tolerance = 1e-6; | ||||||
| settings.presolver = cuopt::linear_programming::presolver_t::Default; | ||||||
| settings.reliability_branching = reliability_branching; | ||||||
| settings.clique_cuts = -1; | ||||||
| settings.seed = 42; | ||||||
| settings.bnb_work_unit_scale = 1; | ||||||
| settings.gpu_heur_work_unit_scale = 0.4; | ||||||
| settings.mip_scaling = false; | ||||||
| settings.gpu_heur_wait_for_exploration = false; | ||||||
| cuopt::linear_programming::benchmark_info_t benchmark_info; | ||||||
| settings.benchmark_info_ptr = &benchmark_info; | ||||||
| auto start_run_solver = std::chrono::high_resolution_clock::now(); | ||||||
| incumbent_tracker_t incumbent_tracker(start_run_solver); | ||||||
| settings.set_mip_callback(&incumbent_tracker); | ||||||
| auto solution = cuopt::linear_programming::solve_mip(&handle_, mps_data_model, settings); | ||||||
| CUOPT_LOG_INFO( | ||||||
| "first obj: %f last improvement of best feasible: %f last improvement after recombination: %f", | ||||||
| benchmark_info.objective_of_initial_population, | ||||||
| benchmark_info.last_improvement_of_best_feasible, | ||||||
| benchmark_info.last_improvement_after_recombination); | ||||||
| // solution.write_to_sol_file(base_filename + ".sol", handle_.get_stream()); | ||||||
| // 1solution.write_to_sol_file(base_filename + ".sol", handle_.get_stream()); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove debug prefix from comment. The commented-out code has 🔧 Proposed fix- // 1solution.write_to_sol_file(base_filename + ".sol", handle_.get_stream());
+ // solution.write_to_sol_file(base_filename + ".sol", handle_.get_stream());📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| std::chrono::milliseconds duration; | ||||||
| auto end = std::chrono::high_resolution_clock::now(); | ||||||
| duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start_run_solver); | ||||||
|
|
@@ -253,7 +325,13 @@ int run_single_file(std::string file_path, | |||||
| << benchmark_info.last_improvement_after_recombination << "," << mip_gap << "," << is_optimal | ||||||
| << "\n"; | ||||||
| write_to_output_file(out_dir, base_filename, device, n_gpus, batch_id, ss.str()); | ||||||
| CUOPT_LOG_INFO("Results written to the file %s", base_filename.c_str()); | ||||||
| if (!out_dir.empty()) { | ||||||
| std::string mps_stem = base_filename.substr(0, base_filename.find(".mps")); | ||||||
| std::string csv_path = out_dir + "/" + mps_stem + "_incumbents.csv"; | ||||||
| incumbent_tracker.write_csv(csv_path); | ||||||
| CUOPT_LOG_INFO( | ||||||
| "Incumbent trace (%zu entries) written to %s", incumbent_tracker.size(), csv_path.c_str()); | ||||||
| } | ||||||
| return sol_found; | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -527,7 +605,7 @@ int main(int argc, char* argv[]) | |||||
| sleep(1); | ||||||
| } | ||||||
| int remaining = paths.size() - tests_ran; | ||||||
| // wait for all processes to finish | ||||||
| // Wait for all processes to finish | ||||||
| for (int i = 0; i < remaining; ++i) { | ||||||
| return_gpu_to_the_queue(pid_gpu_map, pid_file_map, gpu_queue); | ||||||
| } | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,249 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <ComputeSanitizerOutput> | ||
| <record> | ||
| <kind>Initcheck</kind> | ||
| <what> | ||
| <text>Uninitialized __global__ memory read of size 4 bytes</text> | ||
| <size>4</size> | ||
| </what> | ||
| <where> | ||
| <func>.*</func> | ||
| </where> | ||
| <hostStack> | ||
| <frame> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>cusparseCsr2cscEx2</func> | ||
| <module>.*libcusparse.so.*</module> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <record> | ||
| <kind>Initcheck</kind> | ||
| <what> | ||
| <text>Uninitialized __global__ memory read of size 4 bytes</text> | ||
| <size>4</size> | ||
| </what> | ||
| <where> | ||
| <func>ThreadLoad</func> | ||
| </where> | ||
| <hostStack> | ||
| <frame> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>libcudart.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>cudaLaunchKernel</func> | ||
| </frame> | ||
| <frame> | ||
| <func>.*cub::.*::Device(Segmented)?(Reduce|Scan)(SingleTile)?Kernel.*</func> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <record> | ||
| <kind>Initcheck</kind> | ||
| <what> | ||
| <text>Uninitialized __global__ memory read of size 2 bytes</text> | ||
| <size>2</size> | ||
| </what> | ||
| <where> | ||
| <func>ThreadLoad</func> | ||
| </where> | ||
| <hostStack> | ||
| <frame> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>libcudart.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>cudaLaunchKernel</func> | ||
| </frame> | ||
| <frame> | ||
| <func>.*cub::.*::Device(Segmented)?(Reduce|Scan)(SingleTile)?Kernel.*</func> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <record> | ||
| <kind>Initcheck</kind> | ||
| <what> | ||
| <text>Uninitialized __global__ memory read of size 8 bytes</text> | ||
| <size>8</size> | ||
| </what> | ||
| <where> | ||
| <func>DeviceSegmentedReduceKernel</func> | ||
| </where> | ||
| </record> | ||
| <record> | ||
| <kind>Initcheck</kind> | ||
| <what> | ||
| <text>Uninitialized __global__ memory read of size 4 bytes</text> | ||
| <size>4</size> | ||
| </what> | ||
| <where> | ||
| <func>ThreadLoad</func> | ||
| </where> | ||
| <hostStack> | ||
| <frame> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>libcudart.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>libcudart.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcuopt.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>.*Device(Reduce|Scan)Kernel.*</func> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <!-- Rule matching cccl's pattern of copying tuples back to host after reduce_by_keys, which contain uninitialized padding --> | ||
| <!-- Because of aggressive inlining, thrust calls are elided out of the host stack, which prevents a more finely grained rule. In practice this is good enough --> | ||
| <record> | ||
| <kind>InitcheckApiError</kind> | ||
| <level>Error</level> | ||
| <what> | ||
| <text>Host API uninitialized memory access</text> | ||
| <accessSize>16</accessSize> | ||
| </what> | ||
| <hostStack> | ||
| <frame> | ||
| <func>cuMemcpyDtoHAsync.*</func> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <!-- Suppress uninit copies on rmm::device_vector copy constructor - often vector members are allocated but not filled --> | ||
| <record> | ||
| <kind>InitcheckApiError</kind> | ||
| <level>Error</level> | ||
| <what> | ||
| <text>Host API uninitialized memory access</text> | ||
| </what> | ||
| <hostStack> | ||
| <frame> | ||
| <func>cuMemcpyAsync</func> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*librmm.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>rmm::device_buffer::device_buffer</func> | ||
| <module>.*librmm.so.*</module> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <!-- Suppress likely harmless Thrust/CUB tuple-buffer initcheck reads during sort_by_key | ||
| in trivial_presolve's COO->CSC reorder. Source and destination arrays are validated | ||
| immediately before the sort; the warning appears to come from internal tuple staging. --> | ||
| <record> | ||
| <kind>Initcheck</kind> | ||
| <what> | ||
| <text>Uninitialized __global__ memory read</text> | ||
| </what> | ||
| <where> | ||
| <func>transform_kernel</func> | ||
| </where> | ||
| <hostStack> | ||
| <frame> | ||
| <func>cuLaunchKernel_ptsz</func> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>cudaLaunchKernel_ptsz</func> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <record> | ||
| <kind>InitcheckApiError</kind> | ||
| <level>Error</level> | ||
| <what> | ||
| <text>Host API uninitialized memory access</text> | ||
| </what> | ||
| <hostStack> | ||
| <frame> | ||
| <func>cuMemcpyAsync</func> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*librmm.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*librmm.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>rmm::device_uvector.*::device_uvector</func> | ||
| <module>.*libcuopt.so.*</module> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <!-- Uninitialized device-to-device copies are usually harmless - if actualy bogus, errors may be caught later on --> | ||
| <record> | ||
| <kind>InitcheckApiError</kind> | ||
| <level>Error</level> | ||
| <what> | ||
| <text>Host API uninitialized memory access</text> | ||
| </what> | ||
| <hostStack> | ||
| <frame> | ||
| <func>cuMemcpyDtoDAsync.*</func> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| <record> | ||
| <kind>InitcheckApiError</kind> | ||
| <level>Error</level> | ||
| <what> | ||
| <text>Host API uninitialized memory access</text> | ||
| </what> | ||
| <hostStack> | ||
| <frame> | ||
| <func>cuMemcpyAsync</func> | ||
| <module>.*libcuda.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <module>.*libcudart.so.*</module> | ||
| </frame> | ||
| <frame> | ||
| <func>cudaMemcpyAsync</func> | ||
| </frame> | ||
| <frame> | ||
| <func>rmm::device_buffer::resize</func> | ||
| <module>.*librmm.so.*</module> | ||
| </frame> | ||
| </hostStack> | ||
| </record> | ||
| </ComputeSanitizerOutput> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debug prefix from log message.
The log message contains
"1run_mip"which appears to be a debug artifact. This should be"run_mip".🔧 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents