Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions cpp/include/cuopt/utilities/timestamp_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <string>

namespace cuopt {
namespace utilities {

/**
* @brief Check if extra timestamps should be printed based on environment variable
*
* Checks the CUOPT_EXTRA_TIMESTAMPS environment variable once and caches the result.
* Returns true if the environment variable is set to "True", "true", or "1".
*
* @return true if extra timestamps are enabled, false otherwise
*/
bool extraTimestamps();

/**
* @brief Get current timestamp as seconds since epoch
*
* @return Current timestamp as a double representing seconds since epoch
*/
double getCurrentTimestamp();

/**
* @brief Print a timestamp with label if extra timestamps are enabled
*
* @param label The label to print with the timestamp
*/
void printTimestamp(const std::string& label);

} // namespace utilities
} // namespace cuopt
3 changes: 2 additions & 1 deletion cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@

set(UTIL_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/utilities/seed_generator.cu
${CMAKE_CURRENT_SOURCE_DIR}/utilities/logger_helper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/version_info.cpp)
${CMAKE_CURRENT_SOURCE_DIR}/utilities/version_info.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/timestamp_utils.cpp)

add_subdirectory(linear_programming)
add_subdirectory(math_optimization)
Expand Down
14 changes: 14 additions & 0 deletions cpp/src/linear_programming/cuopt_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
#include <cuopt/linear_programming/solve.hpp>
#include <cuopt/linear_programming/solver_settings.hpp>
#include <cuopt/logger.hpp>
#include <cuopt/utilities/timestamp_utils.hpp>

#include <mps_parser/parser.hpp>

#include <cuopt/version_config.hpp>

#include <cstdlib>
#include <memory>
#include <string>

Expand Down Expand Up @@ -115,6 +117,8 @@ cuopt_int_t cuOptCreateProblem(cuopt_int_t num_constraints,
const char* variable_types,
cuOptOptimizationProblem* problem_ptr)
{
cuopt::utilities::printTimestamp("CUOPT_CREATE_PROBLEM");

if (problem_ptr == nullptr || objective_coefficients == nullptr ||
constraint_matrix_row_offsets == nullptr || constraint_matrix_column_indices == nullptr ||
constraint_matrix_coefficent_values == nullptr || constraint_sense == nullptr ||
Expand Down Expand Up @@ -170,6 +174,8 @@ cuopt_int_t cuOptCreateRangedProblem(cuopt_int_t num_constraints,
const char* variable_types,
cuOptOptimizationProblem* problem_ptr)
{
cuopt::utilities::printTimestamp("CUOPT_CREATE_PROBLEM");

if (problem_ptr == nullptr || objective_coefficients == nullptr ||
constraint_matrix_row_offsets == nullptr || constraint_matrix_column_indices == nullptr ||
constraint_matrix_coefficent_values == nullptr || constraint_lower_bounds == nullptr ||
Expand Down Expand Up @@ -596,6 +602,8 @@ cuopt_int_t cuOptSolve(cuOptOptimizationProblem problem,
cuOptSolverSettings settings,
cuOptSolution* solution_ptr)
{
cuopt::utilities::printTimestamp("CUOPT_SOLVE_START");

if (problem == nullptr) { return CUOPT_INVALID_ARGUMENT; }
if (settings == nullptr) { return CUOPT_INVALID_ARGUMENT; }
if (solution_ptr == nullptr) { return CUOPT_INVALID_ARGUMENT; }
Expand All @@ -614,6 +622,9 @@ cuopt_int_t cuOptSolve(cuOptOptimizationProblem problem,
solution_and_stream_view->mip_solution_ptr = new mip_solution_t<cuopt_int_t, cuopt_float_t>(
solve_mip<cuopt_int_t, cuopt_float_t>(*op_problem, mip_settings));
*solution_ptr = static_cast<cuOptSolution>(solution_and_stream_view);

cuopt::utilities::printTimestamp("CUOPT_SOLVE_RETURN");

return static_cast<cuopt_int_t>(
solution_and_stream_view->mip_solution_ptr->get_error_status().get_error_type());
} else {
Expand All @@ -629,6 +640,9 @@ cuopt_int_t cuOptSolve(cuOptOptimizationProblem problem,
new optimization_problem_solution_t<cuopt_int_t, cuopt_float_t>(
solve_lp<cuopt_int_t, cuopt_float_t>(*op_problem, pdlp_settings));
*solution_ptr = static_cast<cuOptSolution>(solution_and_stream_view);

cuopt::utilities::printTimestamp("CUOPT_SOLVE_RETURN");

return static_cast<cuopt_int_t>(
solution_and_stream_view->lp_solution_ptr->get_error_status().get_error_type());
}
Expand Down
61 changes: 61 additions & 0 deletions cpp/src/utilities/timestamp_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <cuopt/utilities/timestamp_utils.hpp>

#include <chrono>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <string>

namespace cuopt {
namespace utilities {

bool extraTimestamps()
{
static bool initialized = false;
static bool enableTimestamps = false;

if (!initialized) {
const char* envValue = std::getenv("CUOPT_EXTRA_TIMESTAMPS");
if (envValue != nullptr) {
std::string value(envValue);
enableTimestamps = (value == "True" || value == "true" || value == "1");
}
initialized = true;
}

return enableTimestamps;
}

double getCurrentTimestamp()
{
auto now = std::chrono::system_clock::now();
return std::chrono::duration<double>(now.time_since_epoch()).count();
}

void printTimestamp(const std::string& label)
{
if (extraTimestamps()) {
std::cout << std::fixed << std::setprecision(6);
std::cout << std::endl << label << ": " << getCurrentTimestamp() << std::endl;
}
}

} // namespace utilities
} // namespace cuopt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import time

from . import data_model_wrapper
from .utilities import catch_cuopt_exception

Expand Down Expand Up @@ -151,6 +154,12 @@ class DataModel(data_model_wrapper.DataModel):
"""

def __init__(self):
if os.environ.get("CUOPT_EXTRA_TIMESTAMPS", False) in (
True,
"True",
"true",
):
print(f"CUOPT_CREATE_PROBLEM: {time.time()}")
super().__init__()

@catch_cuopt_exception
Expand Down
4 changes: 3 additions & 1 deletion python/cuopt/cuopt/linear_programming/problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.


import copy
from enum import Enum

Expand Down Expand Up @@ -767,6 +768,8 @@ def _from_data_model(self, dm):
raise Exception("Couldn't initialize constraints")

def _to_data_model(self):
dm = data_model.DataModel()

# iterate through the constraints and construct the constraint matrix
n = len(self.vars)
self.rhs = []
Expand Down Expand Up @@ -812,7 +815,6 @@ def _to_data_model(self):
self.var_names.append(self.vars[j].VariableName)

# Initialize datamodel
dm = data_model.DataModel()
dm.set_csr_constraint_matrix(
np.array(self.constraint_csr_matrix["values"]),
np.array(self.constraint_csr_matrix["column_indices"]),
Expand Down
17 changes: 16 additions & 1 deletion python/cuopt/cuopt/linear_programming/solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import time

from cuopt.linear_programming.solver import solver_wrapper
from cuopt.linear_programming.solver_settings import SolverSettings
from cuopt.utilities import catch_cuopt_exception
Expand Down Expand Up @@ -78,6 +81,15 @@ def Solve(data_model, solver_settings=None):
>>> # Print the value of one specific variable
>>> print(solution.get_vars()["var_name"])
"""

emit_stamps = os.environ.get("CUOPT_EXTRA_TIMESTAMPS", False) in (
True,
"True",
"true",
)
if emit_stamps:
print(f"CUOPT_SOLVE_START: {time.time()}")

if solver_settings is None:
solver_settings = SolverSettings()

Expand All @@ -95,11 +107,14 @@ def is_mip(var_types):
# Mixed types - fallback to comprehensive check
return any(vt == "I" or vt == b"I" for vt in var_types)

return solver_wrapper.Solve(
s = solver_wrapper.Solve(
data_model,
solver_settings,
mip=is_mip(data_model.get_variable_types()),
)
if emit_stamps:
print(f"CUOPT_SOLVE_RETURN: {time.time()}")
return s


@catch_cuopt_exception
Expand Down