Getting more accurate core utilization in percentage inXMOS Topic is solved

Technical questions regarding the XTC tools and programming with XMOS.
mozcelikors
Experienced Member
Posts: 75
Joined: Sat May 07, 2016 11:47 am

Post by mozcelikors »

Okay I solved the debug_printf problem by updating my xTIMEComposer and creating a new project.

Now, you say regarding the core usage:
- Just trust the figures. Work with them.
- Your tasks are idle most of the time. Thats why.

Is it correct?

But still, there is this issue unresolved:

Code: Select all

on tile[0].core[6]:              Task_ControlLightSystem (PortLightSystem_TH, PortLightSystem_ST, lightstate_interface);
results in:

Code: Select all

tile[8002]: 0 0 0 0 0 0 100 0

Code: Select all

on tile[0].core[7]:              Task_ControlLightSystem (PortLightSystem_TH, PortLightSystem_ST, lightstate_interface);
also results in:

Code: Select all

tile[8002]: 0 0 0 0 0 0 100 0


View Solution
Gothmag
XCore Addict
Posts: 129
Joined: Wed May 11, 2016 3:50 pm

Post by Gothmag »

If that's all that's running I'd assume it's because you're catching a thread when its busy every time, possibly the thread checking usage? I know you can specify a core to run on but I'm not sure how rigid it is on where it actually runs it or if it really actually matters as far as the underlying hardware goes. If you can get core id from each thread and report it to the poller before it starts, probably by delaying its entry to the loop so others can start, you could re-order the numbers to make the order match your representation if it's necessary.

If you try my version which doesn't use a combinable function and polls by default it does need it's own core but it should be more accurate whatever your print schedule is. You don't have to use it with floats that was just an example of the resolution you can potentially get. The higher the poll rate the more accurate the results should be and it seems like you're willing to sacrifice a core for better numbers.
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

If that's all that's running I'd assume it's because you're catching a thread when its busy every time, possibly the thread checking usage? I know you can specify a core to run on but I'm not sure how rigid it is on where it actually runs it or if it really actually matters as far as the underlying hardware goes. If you can get core id from each thread and report it to the poller before it starts, probably by delaying its entry to the loop so others can start, you could re-order the numbers to make the order match your representation if it's necessary.
^^ This is correct. In my example I fetched the actual core ID (although I didn't specify it) and printed it so you can see how to do that (it's in xs1.h). It does not in fact relate to 'm' in the on tile[n].core[m] placement - that syntax is just used for grouping rather than hard placement (which actually does not matter); An alternative to [[combine]] in the par.

If it says 100% in one of the columns, then it's probably the core reading the status register, which is definitely not idle at that time by definition!
mozcelikors
Experienced Member
Posts: 75
Joined: Sat May 07, 2016 11:47 am

Post by mozcelikors »

Hello again guys,

Thanks for every suggestion and teachings. Every information was very helpful.

Called the following at the start of some tasks:

Code: Select all

int PrintCoreAndTileInformation(char * Function_Name)
{
    debug_printf("Starting %s task on core ID %d on tile %x\n", Function_Name,
                                                                get_logical_core_id(),
                                                                get_local_tile_id());
    return 1;
}
I see at the end that:

Code: Select all

Starting Task_MonitorCoresInATile task on core ID 1 on tile 8003
Starting xtcp task on core ID 6 on tile 8002
Starting Task_DriveTBLE02S_MotorController task on core ID 1 on tile 8002
Starting Task_ControlLightSystem task on core ID 2 on tile 8002
Starting Task_GetRemoteCommandsViaBluetooth task on core ID 3 on tile 8002
Starting Task_ReadSonarSensors task on core ID 4 on tile 8002
Starting Task_MonitorCoresInATile task on core ID 5 on tile 8002
Starting Task_SteeringServo_MotorController task on core ID 1 on tile 8002
Starting Task_EthernetAppTCPServer task on core ID 0 on tile 8002

tile[8003]: 100.000 0.000 0.001 100.000 100.000 0.000 0.000    
tile[8002]: 0.000 0.076 0.003 0.001 0.046 0.000 100.000  

I'm willing to share what I have at the end so that people who have the same issues could find it:

Code: Select all

#define ONE_MS_TICKS 100000
#define POLLING_MS  (1 * ONE_MS_TICKS) // XS1_TIMER_HZ // 1250
#define PRINT_MS (1000 * ONE_MS_TICKS)

//Uncomment below to see core usages in high precision and in floating point form.
//#define FLOATING_POINT_SHOW

//Not [[combinable]] anymore
void Task_MonitorCoresInATile(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;

      unsigned int core_busy[8];
      unsigned int core_idle[8];
      unsigned int core_usage[8];
      float core_usage_f[8];

      for (t = 0; t <= 7; t++) {
            core_busy[t] = 0;
            core_idle[t] = 0;
      }

      int tile_id = get_local_tile_id();
      int cntr = 0;

      PrintCoreAndTileInformation("Task_MonitorCoresInATile");

      while(1)
      {
            select {
                  case print_tmr when timerafter(print_time) :> void:
                        /*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++) {
                                  int numerator = (core_busy[t] * 100);
                                  int denominator = (core_idle[t] + core_busy[t]);

                                  if (denominator) {
                                      core_usage[t] = core_usage[t] + numerator / denominator;
                                  } else {
                                      core_usage[t] = core_usage[t] + 0;
                                  }

#ifdef FLOATING_POINT_SHOW
                                  float numerator_f = (core_busy[t] * 100.0f);
                                  float denominator_f = (core_idle[t] + core_busy[t]);
                                  if (denominator_f) {
                                      core_usage_f[t] = core_usage_f[t] + numerator_f / denominator_f;

                                  } else {
                                      core_usage_f[t] = core_usage_f[t] + 0;
                                  }
#endif

                          }

                          cntr = cntr + 1;
                          if (cntr == 5)
                          {
                                  if (core_usage[0]>=0 && core_usage[0]<=500)
                                  {

                                      debug_printf("tile[%x]: %d %d %d %d %d %d %d %d\n\n",tile_id, core_usage[0] /5,
                                                                        core_usage[1] /5,
                                                                        core_usage[2] /5,
                                                                        core_usage[3] /5,
                                                                        core_usage[4] /5,
                                                                        core_usage[5] /5,
                                                                        core_usage[6] /5,
                                                                        core_usage[7] /5);
#ifdef FLOATING_POINT_SHOW
                                      for (int i = 0; i < 8; ++i) core_usage_f[i] /= 5.0f;
                                      printf("tile[%x]: %4.3f %4.3f %4.3f %4.3f %4.3f %4.3f %4.3f %4.3\n\n",tile_id, core_usage_f[0],
                                                              core_usage_f[1],
                                                              core_usage_f[2],
                                                              core_usage_f[3],
                                                              core_usage_f[4],
                                                              core_usage_f[5],
                                                              core_usage_f[6],
                                                              core_usage_f[7]);
#endif

                                      for (t = 0; t <= 7; t++) {
                                          core_usage[t] = 0;
                                          core_usage_f[t] = 0;
                                      }
                                      cntr = 0;
                                  }
                                  else
                                  {
                                        for (t = 0; t <= 7; t++) {
                                            core_usage[t] = 0;
                                            core_usage_f[t] = 0;
                                        }
                                        cntr = 0;
                                  }
                        }

                        for (t = 0; t <= 7; t++) {
                            core_busy[t] = 0;
                            core_idle[t] = 0;
                        }
                        print_time += PRINT_MS;
                        break;


                  //For maximum possible polling rate..
                  default://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) {
                                      if (waiting) {
                                          core_idle[t] += 1;
                                      } else {
                                          core_busy[t] += 1;
                                      }
                              }

                        }
                        break;

                  //For a custom polling rate, specified in core_monitoring.h, please use following instead of default: statement
                  //that is defined above.
                  /*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) {
                                      if (waiting) {
                                          core_idle[t] += 1;
                                      } else {
                                          core_busy[t] += 1;
                                      }
                              }

                        }
                        poll_time += POLLING_MS;
                        break;*/
            }
      }
}
Thanks again to everybody.