Skip to content
Draft
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
125 changes: 124 additions & 1 deletion src/monolithic/gst/inference_elements/base/gva_base_inference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@

#define DEFAULT_SHARE_VADISPLAY_CTX TRUE

#define DEFAULT_CORE_PINNING nullptr

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number 64 appears throughout the code. Consider defining it as a constant for maintainability:

Suggested change
#define DEFAULT_CORE_PINNING nullptr
#define MAX_CPU_CORES 64

Then use MAX_CPU_CORES in all the bounds checks and getter loop instead of hardcoded 64.

Comment on lines +83 to +84
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEFAULT_CORE_PINNING is defined but never used. Please remove it or wire it into the core-pinning property default to avoid dead code and confusion about the intended default behavior.

Suggested change
#define DEFAULT_CORE_PINNING nullptr

Copilot uses AI. Check for mistakes.
G_DEFINE_TYPE_WITH_PRIVATE(GvaBaseInference, gva_base_inference, GST_TYPE_BASE_TRANSFORM);

GST_DEBUG_CATEGORY_STATIC(gva_base_inference_debug_category);
Expand Down Expand Up @@ -115,7 +117,8 @@ enum {
PROP_CUSTOM_PREPROC_LIB,
PROP_CUSTOM_POSTPROC_LIB,
PROP_OV_EXTENSION_LIB,
PROP_SHARE_VADISPLAY_CTX
PROP_SHARE_VADISPLAY_CTX,
PROP_CORE_PINNING
};

GType gst_gva_base_inference_get_inf_region(void) {
Expand Down Expand Up @@ -413,6 +416,12 @@ void gva_base_inference_class_init(GvaBaseInferenceClass *klass) {
"Whether to share VA Display context across inference elements: "
"true (share context, default), false (do not share context)",
DEFAULT_SHARE_VADISPLAY_CTX, param_flags));

g_object_class_install_property(
gobject_class, PROP_CORE_PINNING,
g_param_spec_string("core-pinning", "Core Pinning",
"List or range of CPU cores to pin this inference element to (e.g., '0-3' or '0,2,3')",
nullptr, param_flags));
Comment on lines +420 to +424
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New core-pinning property and parsing logic are introduced here, but there are existing GStreamer pipeline unit tests under tests/unit_tests/tests_gstgva/ that exercise gvadetect/gvaclassify properties. Please add coverage for core-pinning (valid list/range, invalid format, and default behavior) to prevent regressions (especially around parse errors and mask application).

Copilot uses AI. Check for mistakes.
}

void gva_base_inference_cleanup(GvaBaseInference *base_inference) {
Expand Down Expand Up @@ -490,6 +499,60 @@ void gva_base_inference_cleanup(GvaBaseInference *base_inference) {
base_inference->ov_extension_lib = nullptr;
}

/**
* Set the core pinning mask
* 1. Get the current process CPU affinity mask to use as the default core pinning mask.
* 2. If the process affinity mask includes all available cores, and the CPU is PTL-H series,
* limit the default core pinning mask to the first 4 cores (the P-Cores) to optimize performance.
*/
void set_core_pinning_mask(GvaBaseInference *base_inference) {
base_inference->core_pinning_mask = ~0ULL; // by default, all cores are available for pinning
#ifndef _WIN32
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);

auto cpu_set_to_bitmask = [&num_cores](const cpu_set_t *cpu_set) -> guint64 {
guint64 bitmask = 0;
for (int i = 0; i < num_cores; ++i) {
if (CPU_ISSET(i, cpu_set)) {
bitmask |= (1ULL << i);
}
}
Comment on lines +513 to +519
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cpu_set_to_bitmask iterates i < num_cores and does bitmask |= (1ULL << i). If the system has 64+ online cores, shifting by >=64 is undefined behavior and the 64-bit mask can’t represent those cores anyway. Cap the loop at 64 (or at least guard if (i < 64)), and document/handle truncation explicitly.

Copilot uses AI. Check for mistakes.
return bitmask;
};

cpu_set_t process_affinity_mask;
CPU_ZERO(&process_affinity_mask);
pthread_t current_thread = pthread_self();
// Get current CPU affinity mask
if (!pthread_getaffinity_np(current_thread, sizeof(cpu_set_t), &process_affinity_mask)) {
Comment on lines +508 to +527
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file now uses sysconf, cpu_set_t/CPU_* macros, and pthread_getaffinity_np, but it doesn’t include the required headers (commonly <unistd.h>, <sched.h>, <pthread.h> under Linux, and <windows.h> under Windows for GetProcessAffinityMask). Add explicit includes under the existing _WIN32 guards to avoid relying on transitive includes and to prevent build breaks.

Copilot uses AI. Check for mistakes.
// Successfully got the affinity mask, convert it to bitmask for core pinning
base_inference->core_pinning_mask = cpu_set_to_bitmask(&process_affinity_mask);
// Check if all cores are available for pinning
if(CPU_COUNT(&process_affinity_mask) == num_cores) {
// All CPU cores are available for pinning
if(Utils::isCPUPTLHSeries() && num_cores == TOTAL_CORES_PTL_H) {
base_inference->core_pinning_mask = 0xF; // Pin to first 4 cores , the P-Cores
}
}
}
else {
GST_WARNING_OBJECT(base_inference, "Failed to get CPU affinity mask, core pinning will not be limited by process affinity");
}
#else
DWORD_PTR processAffinityMask = 0;
DWORD_PTR systemAffinityMask = 0;
HANDLE current_process = GetCurrentProcess();
if (GetProcessAffinityMask(current_process, &processAffinityMask, &systemAffinityMask)) {
base_inference->core_pinning_mask = processAffinityMask;
if (processAffinityMask == systemAffinityMask) {
// All CPU cores are available for pinning
//if(Utils::isCPUPTLHSeries()) {
// base_inference->core_pinning_mask = 0xF; // Pin to first 4 cores , the P-Cores
//}
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _WIN32 branch of set_core_pinning_mask has an unterminated if (GetProcessAffinityMask(...)) { block: there’s no closing } before #endif, which will break Windows builds. Ensure all opened braces in the Windows branch are properly closed before the #endif and the function’s closing brace.

Suggested change
}
}
}

Copilot uses AI. Check for mistakes.
#endif
}

void gva_base_inference_init(GvaBaseInference *base_inference) {
GST_DEBUG_OBJECT(base_inference, "gva_base_inference_init");

Expand Down Expand Up @@ -545,6 +608,8 @@ void gva_base_inference_init(GvaBaseInference *base_inference) {
base_inference->ov_extension_lib = g_strdup(DEFAULT_OV_EXTENSION_LIB);

base_inference->share_va_display_ctx = DEFAULT_SHARE_VADISPLAY_CTX;

set_core_pinning_mask(base_inference);
}

GstStateChangeReturn gva_base_inference_change_state(GstElement *element, GstStateChange transition) {
Expand Down Expand Up @@ -615,6 +680,48 @@ void gva_base_inference_set_labels(GvaBaseInference *base_inference, const gchar
}
}

// Convert range of integer IDs to bitset representing cores for pinning.
// Example input: "1-5, 8, 10-12"
void gva_base_inference_set_core_pinning(GvaBaseInference *base_inference, const gchar *range_str) {
guint64 core_mask = 0;
Copy link
Copy Markdown
Contributor

@mholowni mholowni Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a possibility that we have a CPU with more than 64 cores?


try {
// Split by comma to get individual ranges or numbers
std::string str(range_str);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a full copy of the input string, then std::istringstream on line 636 copies it again. For a read-only parameter, this can be wasteful.

Since this is C++17 code (using std::from_chars would be better anyway), consider using std::string_view for the parameter:

void gva_base_inference_set_core_pinning(GvaBaseInference *base_inference, 
                                          const gchar *range_str) {
    std::string_view sv(range_str);
    // Then parse sv directly without copying
}

Or better yet, pass through to a helper function that takes std::string_view to avoid C string → string_view conversion overhead in the common path. 📎

std::istringstream iss(str);
std::string part;
Comment on lines +685 to +692
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gva_base_inference_set_core_pinning constructs std::string str(range_str); without checking for range_str == nullptr. Since the property default is nullptr, and users can also set the property to NULL via g_object_set, this can crash. Handle null/empty strings explicitly (e.g., treat as “no override” and keep the existing mask, or report a settings error).

Copilot uses AI. Check for mistakes.

// parse input string and set bits in core_pinning accordingly
while (std::getline(iss, part, ',')) {
// Trim whitespace
part.erase(0, part.find_first_not_of(" \t"));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace trimming only handles spaces and tabs. Consider using a more robust approach that handles all whitespace characters (including newlines, carriage returns, etc.):

Suggested change
part.erase(0, part.find_first_not_of(" \t"));
// Trim whitespace
auto is_space = [](unsigned char c) { return std::isspace(c); };
part.erase(0, std::find_if_not(part.begin(), part.end(), is_space) - part.begin());
part.erase(std::find_if_not(part.rbegin(), part.rend(), is_space).base(), part.end());

This handles all standard whitespace characters and is more maintainable.

part.erase(part.find_last_not_of(" \t") + 1);

if (part.find('-') != std::string::npos) {
// Parse range like "1-5"
size_t dash_pos = part.find('-');
int start = std::stoi(part.substr(0, dash_pos));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::stoi throws exceptions on invalid input, which is expensive for control flow. For performance-critical parsing, use C++17's std::from_chars which is:

  • Exception-free (returns error code)
  • Significantly faster (~10x in benchmarks)
  • Doesn't allocate or use locale
#include <charconv>

int start, end;
auto [ptr1, ec1] = std::from_chars(part.data(), part.data() + dash_pos, start);
auto [ptr2, ec2] = std::from_chars(part.data() + dash_pos + 1, part.data() + part.size(), end);
if (ec1 == std::errc{} && ec2 == std::errc{}) {
    // Valid parse
} else {
    // Handle error without exception overhead
}

Applies to lines 648, 649, and 657.

int end = std::stoi(part.substr(dash_pos + 1));

// Set bits in the range
for (int i = start; i <= end; i++) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing bounds validation causes undefined behavior when core index >= 64. Shifting a 64-bit value by >= 64 bits is UB per C++ standard. Consider adding validation:

Suggested change
for (int i = start; i <= end; i++) {
// Set bits in the range
for (int i = start; i <= end; i++) {
if (i >= 0 && i < 64) {
core_mask |= (1ULL << i);
} else {
GST_WARNING_OBJECT(base_inference, "Core index %d out of range [0-63], skipping", i);
}
}

core_mask |= (1ULL << i);
}
} else {
// Set single bit
core_mask |= (1ULL << std::stoi(part));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the range loop: missing bounds check before bit shift. Consider adding validation:

Suggested change
core_mask |= (1ULL << std::stoi(part));
// Set single bit
int core_id = std::stoi(part);
if (core_id >= 0 && core_id < 64) {
core_mask |= (1ULL << core_id);
} else {
GST_WARNING_OBJECT(base_inference, "Core index %d out of range [0-63], skipping", core_id);
}

}
Comment on lines +700 to +713
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gva_base_inference_set_core_pinning builds a uint64_t mask using 1ULL << i where i comes from user input/ranges. Negative core IDs (e.g. "-1") or IDs >= 64 will cause undefined behavior when shifting. Validate parsed core IDs (and ranges) are within [0, 63] (and ideally within available CPU cores) before shifting/setting bits.

Copilot uses AI. Check for mistakes.
}

} catch (const std::exception &e) {
GST_ELEMENT_ERROR(base_inference, RESOURCE, SETTINGS, ("Invalid core-pinning format"),
("Failed to parse core-pinning property: %s", e.what()));
}

// if string parsed without errrors, update core pinning
base_inference->core_pinning_mask = core_mask;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is outside the try/catch block. When parsing fails, core_mask remains 0 (from line 631 initialization) and gets assigned to core_pinning_mask, which silently disables all cores and overwrites any previously valid configuration.

Consider moving the assignment inside the try block after successful parsing to preserve the existing value on error:

Suggested change
base_inference->core_pinning_mask = core_mask;
} catch (const std::exception &e) {
GST_ELEMENT_ERROR(base_inference, RESOURCE, SETTINGS, ("Invalid core-pinning format"),
("Failed to parse core-pinning property: %s", e.what()));
return; // Preserve existing core_pinning_mask on error
}
// If string parsed without errors, update core pinning
base_inference->core_pinning_mask = core_mask;

}
Comment on lines +716 to +723
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If parsing core-pinning fails, the catch logs an error but the function still overwrites core_pinning_mask with core_mask (which is 0 on error). That can later produce an empty cpu_set_t and make pthread_setaffinity_np fail. Only update core_pinning_mask when parsing succeeds; on error, keep the previous/default mask (or explicitly restore it).

Copilot uses AI. Check for mistakes.

void gva_base_inference_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {
GvaBaseInference *base_inference = GVA_BASE_INFERENCE(object);

Expand Down Expand Up @@ -744,6 +851,9 @@ void gva_base_inference_set_property(GObject *object, guint property_id, const G
case PROP_SHARE_VADISPLAY_CTX:
base_inference->share_va_display_ctx = g_value_get_boolean(value);
break;
case PROP_CORE_PINNING:
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike several other property setters in this file (e.g., model, model-proc, labels) that check check_gva_base_inference_stopped() and warn/error when changed at runtime, core-pinning is applied unconditionally. Since affinity is only set during model creation, changing core-pinning while the element is running likely won’t take effect. Consider enforcing the same “only mutable while stopped” rule (or re-applying affinity when changed) to avoid a misleading runtime-configurable property.

Suggested change
case PROP_CORE_PINNING:
case PROP_CORE_PINNING:
if (GST_STATE(base_inference) > GST_STATE_READY) {
GST_WARNING_OBJECT(base_inference,
"core-pinning property can only be changed while the element is stopped");
break;
}

Copilot uses AI. Check for mistakes.
gva_base_inference_set_core_pinning(base_inference, g_value_get_string(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
Expand Down Expand Up @@ -837,6 +947,19 @@ void gva_base_inference_get_property(GObject *object, guint property_id, GValue
case PROP_SCHEDULING_POLICY:
g_value_set_string(value, base_inference->scheduling_policy);
break;
case PROP_CORE_PINNING: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getter outputs individual cores ("0,1,2,3") while the setter accepts range notation ("0-3"). This asymmetry means:

  • Setting "0-3" then getting returns "0,1,2,3"
  • Copy-pasting the getter output works, but loses the compact representation

Consider implementing range compaction in the getter to match the setter's format. For example:

  • Consecutive cores 0,1,2,3 → "0-3"
  • Non-consecutive 0,2,5,6,7 → "0,2,5-7"

This makes the property symmetric and more user-friendly for large core counts.

// Convert core pinning mask back to string representation for get_property
std::string range_str;
guint64 mask = base_inference->core_pinning_mask;
for (int i = 0; i < 64; i++) {
if (mask & (1ULL << i)) {
if (!range_str.empty())
range_str += ",";
range_str += std::to_string(i);
}
}
g_value_set_string(value, range_str.c_str());
} break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ typedef struct _GvaBaseInference {
gboolean no_block;
gboolean reshape;
gboolean share_va_display_ctx;
guint64 core_pinning_mask;
guint inference_interval;
guint batch_size;
gint batch_timeout;
Expand Down
37 changes: 37 additions & 0 deletions src/monolithic/gst/inference_elements/base/inference_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,10 @@ InferenceImpl::Model InferenceImpl::CreateModel(GvaBaseInference *gva_base_infer
ie_config[KEY_BASE]["frame-height"] = std::to_string(gva_base_inference->info->height);
}

// Set affinity mask that might set as the result of set_core_pinning_mask() call or
// set by the user directly via the core-pinning attribute.
SetAffinityMask(gva_base_inference->core_pinning_mask);

auto image_inference = ImageInference::createImageInferenceInstance(
memory_type, ie_config, allocator.get(), std::bind(&InferenceImpl::InferenceCompletionCallback, this, _1, _2),
std::bind(&InferenceImpl::PushFramesIfInferenceFailed, this, _1), std::move(va_dpy));
Expand Down Expand Up @@ -977,6 +981,39 @@ bool InferenceImpl::IsRoiSizeValid(const GstAnalyticsODMtd roi_meta) {
return w > 1 && h > 1;
}

/**
* Pins current thread to the CPU core set as specified by affinity mask.
*/
void InferenceImpl::SetAffinityMask(uint64_t mask) {
GVA_INFO("Setting CPU affinity mask to 0x%lx\n", mask);
#ifndef _WIN32
cpu_set_t cpuset;
CPU_ZERO(&cpuset); // Initialize to zero
int num_cores = sysconf(_SC_NPROCESSORS_ONLN); // Get number of available CPU cores
for (int core_id = 0; core_id < num_cores; ++core_id) {
Comment on lines +987 to +993
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file now uses cpu_set_t/CPU_SET + pthread_setaffinity_np + sysconf, but it doesn’t include the required platform headers (typically <sched.h>, <pthread.h>, <unistd.h> on Linux, and <windows.h> on Windows). Relying on transitive includes is fragile and may break builds; add the proper includes under the existing _WIN32 guards.

Copilot uses AI. Check for mistakes.
if (mask & (1ULL << core_id)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here mask can have bits set beyond num_cores

The input mask parameter (64-bit) can have bits set for cores that don't exist on the system. For example:

  • System has 16 cores (num_cores = 16)
  • User passes mask 0xFFFFFFFFFFFFFFFF (all 64 bits set)
  • Loop iterates 16 times, but bits 16-63 in mask are never validated
  • CPU_SET gets called only for existing cores, BUT the mask is accepted silently

This creates inconsistency: the user thinks they pinned to cores 0-63, but actually only pinned to 0-15.

Please consider validating mask against actual core count:

// After line 1016
if (mask >= (1ULL << num_cores)) {
    GVA_WARNING("Affinity mask 0x%lx has bits set beyond available cores (%d), truncating\n", mask, num_cores);
    mask &= ((1ULL << num_cores) - 1);  // Clear invalid bits
}

CPU_SET(core_id, &cpuset); // Add the specific core
}
}
Comment on lines +992 to +997
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux affinity code builds a cpu_set_t by iterating core_id < num_cores but shifts 1ULL << core_id. If num_cores >= 64, shifting by >=64 is undefined behavior (and the uint64_t mask cannot represent cores beyond 63 anyway). Consider capping the loop at 64 (or std::min(num_cores, 64)) and/or rejecting masks that reference unsupported core IDs.

Copilot uses AI. Check for mistakes.

pthread_t current_thread = pthread_self(); // Get current thread handle
int result = pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset);

if (result != 0) {
GVA_ERROR("Error pinning thread: (%d)\n", result);
}
Comment on lines +987 to +1004
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetAffinityMask will call pthread_setaffinity_np even when mask == 0, producing an empty cpu_set_t and typically failing with EINVAL. Consider treating mask == 0 as “no pinning requested” (skip setting affinity) or returning/logging a clear error without attempting to set an empty CPU set.

Copilot uses AI. Check for mistakes.
#else
DWORD_PTR mask = static_cast<DWORD_PTR>(&mask);

HANDLE thread = GetCurrentThread(); // Get handle for the current thread
DWORD_PTR result = SetThreadAffinityMask(thread, mask);

Comment on lines +1006 to +1010
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows implementation of affinity pinning is incorrect: it redeclares mask (shadowing the parameter) and casts &mask (address) to DWORD_PTR, which will pass a pointer value instead of the intended bitmask to SetThreadAffinityMask and likely fail or pin unpredictably. Use the incoming uint64_t mask value (converted to DWORD_PTR) and avoid shadowing; also ensure required Windows headers/types are included under _WIN32.

Copilot uses AI. Check for mistakes.
if (result == 0) {
GVA_ERROR("Error pinning thread: (%d)\n", GetLastError());
}
#endif
}

/**
* Acquires output_frames_mutex with std::lock_guard.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class InferenceImpl {
std::list<OutputFrame> output_frames;
std::mutex output_frames_mutex;

void SetAffinityMask(uint64_t mask);
void PushOutput();
bool CheckSrcPadBlocked(GstObject *src);
void PushBufferToSrcPad(OutputFrame &output_frame);
Expand Down
27 changes: 27 additions & 0 deletions src/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,31 @@ std::string fixPath(std::string path) {
return path;
}


bool isCPUPTLHSeries() {
#ifndef _WIN32
std::ifstream in("/proc/cpuinfo");
if (!in.is_open())
return false;

std::string line;
const std::string key = "model name"; //e.g. model name : Intel(R) Core(TM) Ultra X7 358H
while (std::getline(in, line)) {
if (line.rfind(key, 0) == 0) {
auto pos = line.find(':');
if (pos != std::string::npos) {
std::string value = line.substr(pos + 1);
static const std::regex model_regex("\\b3\\d{2}H\\b");
if (std::regex_search(value, model_regex))
return true; // Intel® Core™ Ultra Series 3 processors with 16 cores (H) e.g. 358H
return false;
}
}
}
return false;
#else
return false; // Add support for Windows
#endif
}

} // namespace Utils
13 changes: 13 additions & 0 deletions src/utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
#endif

#define TOTAL_CORES_PTL_H 16

namespace Utils {

const std::string dpcppInstructionMsg = "Seems DPC++ dependency is not installed. Please follow installation guide: "
Expand Down Expand Up @@ -141,6 +143,17 @@ bool checkAllKeysAreKnown(const std::set<std::string> &known_keys, const std::ma
*/
std::string fixPath(std::string path);


#ifndef _WIN32
/*
* @brief Checks if the CPU is from Intel® Core™ Ultra Series 3 processors with 16 cores (H)
* which is a part of PTL-H series.
*
* @return true if the CPU is from Intel® Core™ Ultra Series 3 processors with 16 cores (H),
* false otherwise.
*/
bool isCPUPTLHSeries(void);
#endif
} // namespace Utils

#endif
Loading