rewrite of swiss, swiss will not be public but l4 specific
This commit is contained in:
@@ -27,9 +27,13 @@ NIF_API SIMDID NIF_DECL nif_get_simd_level_global();
|
||||
NIF_API SIMDID NIF_DECL nif_get_simd_level_local();
|
||||
NIF_API SIMDID NIF_DECL nif_get_unite_simd(SIMDID left, SIMDID right);
|
||||
NIF_API int NIF_DECL nif_compare_simd(SIMDID left, SIMDID right);
|
||||
NIF_API void NIF_DECL nif_set_thread_affinity(int core_id, int numa_id);
|
||||
NIF_API void NIF_DECL nif_set_thread_affinity(int cpu_index, int processor_group_id);
|
||||
NIF_API void* NIF_DECL nif_numa_alloc(size_t size, int numa_id);
|
||||
NIF_API void NIF_DECL nif_numa_free(void *ptr, size_t size, int numa_id);
|
||||
NIF_API int NIF_DECL nif_get_numa_each(int numa_id, uint64_t *internal, uint32_t *global);
|
||||
NIF_API int NIF_DECL nif_get_numa_each(int numa_id,
|
||||
uint32_t *processor_group_ids,
|
||||
uint32_t *socket_ids,
|
||||
uint32_t *cpu_indices,
|
||||
uint32_t *numa_node_ids);
|
||||
NIF_API int NIF_DECL nif_get_numa_overall(int *out_numa_count, int *count_of_each_numa);
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,11 @@ typedef struct nif_linux_max_context {
|
||||
} nif_linux_max_context;
|
||||
|
||||
typedef struct nif_linux_fill_cpu_context {
|
||||
uint64_t *internal;
|
||||
uint32_t *global;
|
||||
uint32_t *processor_group_ids;
|
||||
uint32_t *socket_ids;
|
||||
uint32_t *cpu_indices;
|
||||
uint32_t *numa_node_ids;
|
||||
int numa_id;
|
||||
int index;
|
||||
} nif_linux_fill_cpu_context;
|
||||
|
||||
@@ -118,14 +121,37 @@ static int nif_linux_track_max_id(int value, void *context)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nif_linux_read_socket_id(int cpu_id, uint32_t *socket_id)
|
||||
{
|
||||
char path[160];
|
||||
char buffer[64];
|
||||
char *end = NULL;
|
||||
long parsed_value;
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu_id);
|
||||
if (!nif_linux_read_first_line(path, buffer, sizeof(buffer)))
|
||||
return 0;
|
||||
|
||||
errno = 0;
|
||||
parsed_value = strtol(buffer, &end, 10);
|
||||
if (end == buffer || errno == ERANGE || parsed_value < 0 || parsed_value > UINT32_MAX)
|
||||
return 0;
|
||||
|
||||
*socket_id = (uint32_t)parsed_value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nif_linux_fill_cpu_id(int value, void *context)
|
||||
{
|
||||
nif_linux_fill_cpu_context *fill_context = (nif_linux_fill_cpu_context *)context;
|
||||
uint32_t socket_id = 0;
|
||||
if (!nif_linux_read_socket_id(value, &socket_id))
|
||||
return 0;
|
||||
|
||||
if (fill_context->internal != NULL)
|
||||
fill_context->internal[fill_context->index] = (uint64_t)fill_context->index;
|
||||
if (fill_context->global != NULL)
|
||||
fill_context->global[fill_context->index] = (uint32_t)value;
|
||||
fill_context->processor_group_ids[fill_context->index] = 0u;
|
||||
fill_context->socket_ids[fill_context->index] = socket_id;
|
||||
fill_context->cpu_indices[fill_context->index] = (uint32_t)value;
|
||||
fill_context->numa_node_ids[fill_context->index] = (uint32_t)fill_context->numa_id;
|
||||
|
||||
fill_context->index++;
|
||||
return 1;
|
||||
@@ -211,12 +237,14 @@ static int nif_linux_populate_writable_mapping(void *address, size_t size)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Pin the calling thread to a single logical processor.
|
||||
* core_id >= 0 : bind to that logical processor (global index, across groups).
|
||||
* core_id < 0 : clear affinity constraint within the current group. */
|
||||
NIF_API void NIF_DECL nif_set_thread_affinity(int core_id, int numa_id)
|
||||
/* Linux has no Windows-style processor groups; processor_group_id is ignored. */
|
||||
NIF_API void NIF_DECL nif_set_thread_affinity(int cpu_index, int processor_group_id)
|
||||
{
|
||||
int cpu_count = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
(void)processor_group_id;
|
||||
|
||||
int cpu_count = (int)sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (cpu_index >= cpu_count)
|
||||
cpu_count = cpu_index + 1;
|
||||
if (cpu_count <= 0)
|
||||
return;
|
||||
|
||||
@@ -227,11 +255,11 @@ NIF_API void NIF_DECL nif_set_thread_affinity(int core_id, int numa_id)
|
||||
|
||||
CPU_ZERO_S(size, set);
|
||||
|
||||
if (core_id < 0) {
|
||||
if (cpu_index < 0) {
|
||||
for (int i = 0; i < cpu_count; i++)
|
||||
CPU_SET_S((int)i, size, set);
|
||||
} else {
|
||||
CPU_SET_S(core_id, size, set);
|
||||
CPU_SET_S(cpu_index, size, set);
|
||||
}
|
||||
|
||||
pthread_setaffinity_np(pthread_self(), size, set);
|
||||
@@ -264,9 +292,14 @@ NIF_API int NIF_DECL nif_get_numa_overall(int *out_numa_count, int *count_of_eac
|
||||
return 1;
|
||||
}
|
||||
|
||||
NIF_API int NIF_DECL nif_get_numa_each(int numa_id, uint64_t *internal, uint32_t *global)
|
||||
NIF_API int NIF_DECL nif_get_numa_each(int numa_id,
|
||||
uint32_t *processor_group_ids,
|
||||
uint32_t *socket_ids,
|
||||
uint32_t *cpu_indices,
|
||||
uint32_t *numa_node_ids)
|
||||
{
|
||||
if (numa_id < 0)
|
||||
if (numa_id < 0 || processor_group_ids == NULL || socket_ids == NULL ||
|
||||
cpu_indices == NULL || numa_node_ids == NULL)
|
||||
return 0;
|
||||
|
||||
char path[128];
|
||||
@@ -275,7 +308,14 @@ NIF_API int NIF_DECL nif_get_numa_each(int numa_id, uint64_t *internal, uint32_t
|
||||
if (!nif_linux_read_first_line(path, buffer, sizeof(buffer)))
|
||||
return 0;
|
||||
|
||||
nif_linux_fill_cpu_context fill_context = { internal, global, 0 };
|
||||
nif_linux_fill_cpu_context fill_context = {
|
||||
processor_group_ids,
|
||||
socket_ids,
|
||||
cpu_indices,
|
||||
numa_node_ids,
|
||||
numa_id,
|
||||
0
|
||||
};
|
||||
return nif_linux_visit_id_list(buffer, nif_linux_fill_cpu_id, &fill_context);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,33 +3,102 @@
|
||||
|
||||
#if NIF_IS_OS(NIF_OS_WINDOWS)
|
||||
|
||||
/* Pin the calling thread to a single logical processor.
|
||||
* core_id >= 0 : bind to that logical processor (global index, across groups).
|
||||
* core_id < 0 : clear affinity constraint within the current group. */
|
||||
NIF_API void NIF_DECL nif_set_thread_affinity(int core_id, int numa_id)
|
||||
static int nif_windows_get_socket_map(uint32_t **out_socket_map, DWORD *out_group_count)
|
||||
{
|
||||
if (core_id < 0 || numa_id < 0) {
|
||||
/* Query which group the thread currently belongs to */
|
||||
DWORD group_count = GetActiveProcessorGroupCount();
|
||||
DWORD buffer_size = 0;
|
||||
uint32_t *socket_map;
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *information;
|
||||
BYTE *cursor;
|
||||
uint32_t socket_id = 0;
|
||||
|
||||
if (group_count == 0)
|
||||
return 0;
|
||||
|
||||
socket_map = (uint32_t *)malloc((size_t)group_count * 64u * sizeof(uint32_t));
|
||||
if (socket_map == NULL)
|
||||
return 0;
|
||||
for (size_t i = 0; i < (size_t)group_count * 64u; i++)
|
||||
socket_map[i] = UINT32_MAX;
|
||||
|
||||
GetLogicalProcessorInformationEx(RelationProcessorPackage, NULL, &buffer_size);
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || buffer_size == 0) {
|
||||
free(socket_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
information = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)malloc(buffer_size);
|
||||
if (information == NULL ||
|
||||
!GetLogicalProcessorInformationEx(RelationProcessorPackage, information, &buffer_size)) {
|
||||
free(information);
|
||||
free(socket_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cursor = (BYTE *)information;
|
||||
while (cursor < (BYTE *)information + buffer_size) {
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *entry =
|
||||
(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)cursor;
|
||||
if (entry->Relationship == RelationProcessorPackage) {
|
||||
PROCESSOR_RELATIONSHIP *package = &entry->Processor;
|
||||
for (WORD i = 0; i < package->GroupCount; i++) {
|
||||
WORD group = package->GroupMask[i].Group;
|
||||
KAFFINITY mask = package->GroupMask[i].Mask;
|
||||
if (group >= group_count)
|
||||
continue;
|
||||
for (DWORD cpu = 0; cpu < 64; cpu++) {
|
||||
if ((mask & ((KAFFINITY)1 << cpu)) != 0)
|
||||
socket_map[(size_t)group * 64u + cpu] = socket_id;
|
||||
}
|
||||
}
|
||||
socket_id++;
|
||||
}
|
||||
if (entry->Size == 0)
|
||||
break;
|
||||
cursor += entry->Size;
|
||||
}
|
||||
|
||||
free(information);
|
||||
*out_socket_map = socket_map;
|
||||
*out_group_count = group_count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nif_windows_get_processor_node(WORD group, BYTE cpu, USHORT *node_id)
|
||||
{
|
||||
PROCESSOR_NUMBER processor;
|
||||
memset(&processor, 0, sizeof(processor));
|
||||
processor.Group = group;
|
||||
processor.Number = cpu;
|
||||
return GetNumaProcessorNodeEx(&processor, node_id) != 0;
|
||||
}
|
||||
|
||||
/* Pin the calling thread using its processor group and group-local CPU index. */
|
||||
NIF_API void NIF_DECL nif_set_thread_affinity(int cpu_index, int processor_group_id)
|
||||
{
|
||||
if (cpu_index < 0 || processor_group_id < 0) {
|
||||
GROUP_AFFINITY current;
|
||||
GetThreadGroupAffinity(GetCurrentThread(), ¤t);
|
||||
/* Build a full mask for that group's actual core count */
|
||||
DWORD count = GetActiveProcessorCount(current.Group);
|
||||
GROUP_AFFINITY ga;
|
||||
memset(&ga, 0, sizeof(ga));
|
||||
ga.Group = current.Group;
|
||||
ga.Mask = (count >= 64) ? ~(KAFFINITY)0 : ((KAFFINITY)1 << count) - 1;
|
||||
SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL);
|
||||
GROUP_AFFINITY affinity;
|
||||
memset(&affinity, 0, sizeof(affinity));
|
||||
affinity.Group = current.Group;
|
||||
affinity.Mask = (count >= 64) ? ~(KAFFINITY)0 : ((KAFFINITY)1 << count) - 1;
|
||||
SetThreadGroupAffinity(GetCurrentThread(), &affinity, NULL);
|
||||
return;
|
||||
}
|
||||
int index = core_id % 64;
|
||||
DWORD count = GetActiveProcessorCount(numa_id);
|
||||
if ((DWORD)index >= count)
|
||||
|
||||
if ((DWORD)processor_group_id >= GetActiveProcessorGroupCount() || cpu_index >= 64)
|
||||
return;
|
||||
GROUP_AFFINITY ga;
|
||||
memset(&ga, 0, sizeof(ga));
|
||||
ga.Group = (WORD)numa_id;
|
||||
ga.Mask = (KAFFINITY)1 << index;
|
||||
SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL);
|
||||
USHORT node_id = 0;
|
||||
if (!nif_windows_get_processor_node((WORD)processor_group_id, (BYTE)cpu_index, &node_id))
|
||||
return;
|
||||
|
||||
GROUP_AFFINITY affinity;
|
||||
memset(&affinity, 0, sizeof(affinity));
|
||||
affinity.Group = (WORD)processor_group_id;
|
||||
affinity.Mask = (KAFFINITY)1 << cpu_index;
|
||||
SetThreadGroupAffinity(GetCurrentThread(), &affinity, NULL);
|
||||
}
|
||||
|
||||
NIF_API int NIF_DECL nif_get_numa_overall(int *out_numa_count, int *count_of_each_numa)
|
||||
@@ -39,30 +108,60 @@ NIF_API int NIF_DECL nif_get_numa_overall(int *out_numa_count, int *count_of_eac
|
||||
return 0;
|
||||
*out_numa_count = (int)highest + 1;
|
||||
|
||||
for (UCHAR n = 0; n <= (UCHAR)highest; n++) {
|
||||
ULONGLONG mask = 0;
|
||||
GetNumaNodeProcessorMask(n, &mask);
|
||||
count_of_each_numa[n] = (int)__popcnt64(mask);
|
||||
if (count_of_each_numa != NULL) {
|
||||
for (ULONG n = 0; n <= highest; n++)
|
||||
count_of_each_numa[n] = 0;
|
||||
}
|
||||
|
||||
DWORD group_count = GetActiveProcessorGroupCount();
|
||||
for (DWORD group = 0; group < group_count; group++) {
|
||||
for (DWORD cpu = 0; cpu < 64; cpu++) {
|
||||
USHORT node_id = 0;
|
||||
if (nif_windows_get_processor_node((WORD)group, (BYTE)cpu, &node_id) &&
|
||||
count_of_each_numa != NULL && node_id <= highest)
|
||||
count_of_each_numa[node_id]++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
NIF_API int NIF_DECL nif_get_numa_each(int numa_id, uint64_t *internal, uint32_t *global)
|
||||
NIF_API int NIF_DECL nif_get_numa_each(int numa_id,
|
||||
uint32_t *processor_group_ids,
|
||||
uint32_t *socket_ids,
|
||||
uint32_t *cpu_indices,
|
||||
uint32_t *numa_node_ids)
|
||||
{
|
||||
ULONGLONG mask = 0;
|
||||
if (!GetNumaNodeProcessorMask((UCHAR)numa_id, &mask))
|
||||
if (numa_id < 0 || processor_group_ids == NULL || socket_ids == NULL ||
|
||||
cpu_indices == NULL || numa_node_ids == NULL)
|
||||
return 0;
|
||||
|
||||
int intra = 0;
|
||||
while (mask) {
|
||||
DWORD idx;
|
||||
_BitScanForward64(&idx, mask);
|
||||
if (internal != NULL)
|
||||
internal[intra] = (uint64_t)intra;
|
||||
global[intra] = (uint32_t)idx;
|
||||
intra++;
|
||||
mask &= mask - 1;
|
||||
uint32_t *socket_map = NULL;
|
||||
DWORD group_count = 0;
|
||||
if (!nif_windows_get_socket_map(&socket_map, &group_count))
|
||||
return 0;
|
||||
|
||||
int index = 0;
|
||||
for (DWORD group = 0; group < group_count; group++) {
|
||||
for (DWORD cpu = 0; cpu < 64; cpu++) {
|
||||
USHORT node_id = 0;
|
||||
if (!nif_windows_get_processor_node((WORD)group, (BYTE)cpu, &node_id) ||
|
||||
node_id != (USHORT)numa_id)
|
||||
continue;
|
||||
|
||||
uint32_t socket_id = socket_map[(size_t)group * 64u + cpu];
|
||||
if (socket_id == UINT32_MAX) {
|
||||
free(socket_map);
|
||||
return 0;
|
||||
}
|
||||
processor_group_ids[index] = (uint32_t)group;
|
||||
socket_ids[index] = socket_id;
|
||||
cpu_indices[index] = cpu;
|
||||
numa_node_ids[index] = node_id;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
free(socket_map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user