Hello guys,
In my application I need the core load info for each core, is getting that information (and further sending it over some protocol) possible real-time?
NOTE: I'm using xCORE-200 Explorer kit.
Thanks for the information in advance,
Cheers.
Getting Core Utilization/Usage Information on XMOS Topic is solved
-
- Experienced Member
- Posts: 75
- Joined: Sat May 07, 2016 11:47 am
-
- XCore Legend
- Posts: 1913
- Joined: Thu Jun 10, 2010 11:43 am
Perhaps the reply from segher is suitable ?
http://www.xcore.com/forum/viewtopic.php?f=7&t=1633
https://www.xmos.com/download/private/T ... 1.0%29.pdf
* page 41
http://www.xcore.com/forum/viewtopic.php?f=7&t=1633
https://www.xmos.com/download/private/T ... 1.0%29.pdf
* page 41
-
- XCore Addict
- Posts: 230
- Joined: Wed Mar 10, 2010 12:46 pm
There is a better way to do this which gives you the activity levels of cores. In the following code the monitorCores() task prints at a rate defined by the PRINT_MS define and polls at the rate controlled by the PRINT_MS define.
The code has a sample load task which you can specify how many milliseconds to run busy and how many to run idle. The top-level creates a few of these cores on the two tiles.
I used lib_logging because it is light-weight, so you'll need to include the following config.xscope:
When I run it it now prints something like:
which show the idle/busy counts for each core.
Hope that helps,
Peter
The code has a sample load task which you can specify how many milliseconds to run busy and how many to run idle. The top-level creates a few of these cores on the two tiles.
Code: Select all
#include <platform.h>
#include <xs1.h>
#include <stdio.h>
#include "debug_print.h"
#define ONE_MS_TICKS 100000
#define POLLING_MS (1 * ONE_MS_TICKS)
#define PRINT_MS (1000 * ONE_MS_TICKS)
[[combinable]]
void monitorCores()
{
short int t;
timer poll_tmr, print_tmr;
int poll_time, print_time;
poll_tmr :> poll_time;
print_time = poll_time + PRINT_MS;
int core_busy[8];
int core_idle[8];
for (t = 0; t <= 7; t++) {
core_busy[t] = 0;
core_idle[t] = 0;
}
int tile_id = get_local_tile_id();
while(1)
{
select {
case print_tmr when timerafter(print_time) :> void:
debug_printf("tile[%x]: %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d\n",
tile_id,
core_busy[0], core_idle[0],
core_busy[1], core_idle[1],
core_busy[2], core_idle[2],
core_busy[3], core_idle[3],
core_busy[4], core_idle[4],
core_busy[5], core_idle[5],
core_busy[6], core_idle[6],
core_busy[7], core_idle[7]);
for (t = 0; t <= 7; t++) {
core_busy[t] = 0;
core_idle[t] = 0;
}
print_time += PRINT_MS;
break;
case poll_tmr when timerafter(poll_time) :> void:
for (t = 0; t <= 7; t++) {
// Read the processor state
int ps_value = getps(0x100*t+4);
const int in_use = (ps_value & 0x1);
if (in_use) {
// Read the status register
unsigned int sr_value;
read_pswitch_reg(tile_id, XS1_PSWITCH_T0_SR_NUM+t, sr_value);
const int waiting = (sr_value >> 6) & 0x1;
if (waiting) {
core_idle[t] += 1;
} else {
core_busy[t] += 1;
}
}
}
poll_time += POLLING_MS;
break;
}
}
}
void load(int busy_ms, int idle_ms) {
timer tmr;
int time;
tmr :> time;
while (1) {
// Busy time
time += busy_ms * ONE_MS_TICKS;
int busy = 1;
while (busy) {
select {
case tmr when timerafter(time) :> void:
busy = 0;
break;
default:
break;
}
}
// Idle time
time += idle_ms * ONE_MS_TICKS;
tmr when timerafter(time) :> void;
}
}
int main()
{
par {
on tile[0] : monitorCores();
on tile[0] : load(0, 100);
on tile[0] : load(5, 95);
on tile[0] : load(50, 50);
on tile[1] : monitorCores();
on tile[1] : load(50, 50);
on tile[1] : load(10, 90);
on tile[1] : load(1, 99);
}
return 0;
}
Code: Select all
<xSCOPEconfig enabled="true" ioMode="basic">
</xSCOPEconfig>
Code: Select all
tile[8002]: 500/500 1000/0 950/50 1000/0 0/1000 0/1000 0/1000 0/1000
tile[8003]: 990/10 500/500 900/100 1000/0 0/1000 0/1000 0/1000 0/1000
tile[8002]: 500/500 1000/0 950/50 1000/0 0/1000 0/1000 0/1000 0/1000
tile[8003]: 990/10 500/500 900/100 1000/0 0/1000 0/1000 0/1000 0/1000
tile[8002]: 500/500 1000/0 950/50 1000/0 0/1000 0/1000 0/1000 0/1000
tile[8003]: 990/10 500/500 900/100 1000/0 0/1000 0/1000 0/1000 0/1000
tile[8002]: 500/500 1000/0 950/50 1000/0 0/1000 0/1000 0/1000 0/1000
Hope that helps,
Peter
Last edited by peter on Mon Nov 07, 2016 12:55 pm, edited 1 time in total.
Reason: Fixed the code to correct busy/idle.
Reason: Fixed the code to correct busy/idle.
-
- Experienced Member
- Posts: 75
- Joined: Sat May 07, 2016 11:47 am
Hello,
Thanks for the reply, looks like its gonna work.
Could you please check if I correctly transferred it to core utilization percentage. Thanks.
Note: Its either around 100% 99% or 0%. It doesnt feel correct :)
Thanks for the reply, looks like its gonna work.
Could you please check if I correctly transferred it to core utilization percentage. Thanks.
Note: Its either around 100% 99% or 0%. It doesnt feel correct :)
Code: Select all
[[combinable]]
void monitorCores(client core_stats_if core_stats_interface)
{
short int t;
timer poll_tmr, print_tmr;
int poll_time, print_time;
poll_tmr :> poll_time;
print_time = poll_time + PRINT_MS;
float core_busy[8];
float core_idle[8];
short int core_usage[8];
for (t = 0; t <= 7; t++) {
core_busy[t] = 0;
core_idle[t] = 0;
}
int tile_id = get_local_tile_id();
while(1)
{
select {
case print_tmr when timerafter(print_time) :> void:
for (t = 0; t <= 7; t++) {
core_usage[t] = ((float)(core_busy[t] / (core_busy[t] + core_idle[t])))*100;
}
core_stats_interface.ShareCoreUsage (core_usage[0],
core_usage[1],
core_usage[2],
core_usage[3],
core_usage[4],
core_usage[5],
core_usage[6],
core_usage[7]);
/*printf("%d %d %d %d %d %d %d %d\n",core_usage[0],
core_usage[1],
core_usage[2],
core_usage[3],
core_usage[4],
core_usage[5],
core_usage[6],
core_usage[7]);*/
for (t = 0; t <= 7; t++) {
core_busy[t] = 0;
core_idle[t] = 0;
}
print_time += PRINT_MS;
break;
case poll_tmr when timerafter(poll_time) :> void:
for (t = 0; t <= 7; t++) {
// Read the processor state
int ps_value = getps(0x100*t+4);
// Read the status register
unsigned int sr_value;
read_pswitch_reg(tile_id, XS1_PSWITCH_T0_SR_NUM+t, sr_value);
const int in_use = (ps_value & 0x1);
const int waiting = (sr_value >> 6) & 0x1;
if (in_use && waiting) {
core_busy[t] += 1;
} else {
core_idle[t] += 1;
}
}
poll_time += POLLING_MS;
break;
}
}
}
-
- XCore Addict
- Posts: 230
- Joined: Wed Mar 10, 2010 12:46 pm
Please note that I made a mistake in my original post which I corrected, so it should be:
Though this code doesn't count either if the core is not active.
Note that the xCORE doesn't have a floating point unit, so using float will result in slow code. I would recommend you use int instead and simply do:
Just note that the one core that is running this will always look idle because it is always waiting when it reads the status register.
Peter
Code: Select all
if (in_use) {
if (waiting) {
core_idle[t] += 1;
} else {
core_busy[t] += 1;
}
}
Note that the xCORE doesn't have a floating point unit, so using float will result in slow code. I would recommend you use int instead and simply do:
Code: Select all
for (t = 0; t <= 7; t++) {
if (core_idle[t] + core_busy[t]) {
core_usage[t] = (100 * core_busy[t]) / (core_busy[t] + core_idle[t]);
} else {
core_usage[t] = 0;
}
}
Peter
-
- Experienced Member
- Posts: 75
- Joined: Sat May 07, 2016 11:47 am
Thanks for the kind helps. That should work.