* @brief Benchmark multithreaded performance by calculating the Mandelbrot set. * * @param benchmark Whether to perform the full benchmarks. * @param plot Whether to perform quick benchmarks by just plotting the image once. * @param save Whether to save the image as a BMP file. */
| 3597 | * @param save Whether to save the image as a BMP file. |
| 3598 | */ |
| 3599 | void check_performance(const bool benchmark, const bool plot, const bool save) |
| 3600 | { |
| 3601 | print_header("Preparing benchmarks:"); |
| 3602 | |
| 3603 | #ifdef BS_THREAD_POOL_NATIVE_EXTENSIONS |
| 3604 | // Try to give the process the highest possible priority, so that other processes do not interfere with the benchmarks. |
| 3605 | if (!BS::set_os_process_priority(BS::os_process_priority::realtime)) |
| 3606 | if (!BS::set_os_process_priority(BS::os_process_priority::high)) |
| 3607 | BS::set_os_process_priority(BS::os_process_priority::above_normal); |
| 3608 | |
| 3609 | const std::string process_priority = os_process_priority_name(BS::get_os_process_priority()); |
| 3610 | logln("Process priority set to: ", process_priority, "."); |
| 3611 | if (process_priority != "realtime") |
| 3612 | logln_ansi(ansi_info, "Note: Please run as admin/root to enable a higher process priority."); |
| 3613 | |
| 3614 | try_os_thread_priority(); |
| 3615 | const std::string thread_priority = os_thread_priority_name(BS::this_thread::get_os_thread_priority()); |
| 3616 | logln("Thread priority set to: ", thread_priority, "."); |
| 3617 | if (thread_priority != "realtime") |
| 3618 | logln_ansi(ansi_info, "Note: Please run as admin/root to enable a higher thread priority."); |
| 3619 | |
| 3620 | // Initialize a thread pool with the default number of threads, and ensure that the threads have the highest possible priority, so that other processes do not interfere with the benchmarks. |
| 3621 | BS::thread_pool pool(try_os_thread_priority); |
| 3622 | #else |
| 3623 | // If native extensions are disabled, just initialize a thread pool with the default number of threads. |
| 3624 | BS::thread_pool pool; |
| 3625 | #endif |
| 3626 | |
| 3627 | // Store the number of available hardware threads for easy access. |
| 3628 | const std::size_t thread_count = pool.get_thread_count(); |
| 3629 | logln("Using ", thread_count, " threads."); |
| 3630 | |
| 3631 | // Set the formatting of floating point numbers. |
| 3632 | log(std::fixed, std::setprecision(1)); |
| 3633 | |
| 3634 | // Initialize a timer object to measure execution time. |
| 3635 | timer tmr; |
| 3636 | |
| 3637 | // The target execution time, in milliseconds, of the multithreaded test with the number of blocks equal to the number of threads. The total time spent on that test will be approximately equal to `repeat * target_ms`. |
| 3638 | constexpr std::chrono::milliseconds::rep target_ms = 50; |
| 3639 | |
| 3640 | // Find the Mandelbrot image size that will roughly achieve the target execution time. |
| 3641 | logln("Determining the Mandelbrot image size needed to achieve an approximate mean execution time of ", target_ms, " ms with ", thread_count, " tasks..."); |
| 3642 | std::size_t image_size = thread_count; |
| 3643 | image_matrix<color> image; |
| 3644 | std::size_t jump = 1; |
| 3645 | std::size_t offset = 0; |
| 3646 | |
| 3647 | // Define the loop function. |
| 3648 | const auto loop = [&image, &jump, &offset](const std::size_t start, const std::size_t end) |
| 3649 | { |
| 3650 | calculate_mandelbrot(image, start, end, jump, offset); |
| 3651 | }; |
| 3652 | |
| 3653 | // Increase the image size gradually until the target execution time is reached. |
| 3654 | do |
| 3655 | { |
| 3656 | image_size *= 2; |
no test coverage detected