Used chanends with declared but unused interfaces

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
atena
Member
Posts: 12
Joined: Fri Apr 25, 2014 3:35 pm

Used chanends with declared but unused interfaces

Post by atena »

Hi all,

As a requirement, I am widely using arrays of interfaces as arguments of my function libraries.

Code: Select all

void foo(interface bar server i_bar[5]);
From all the interfaces available within the arrays, not always all interfaces are instantiated in both ends. However, as soon as I have 32 Interfaces declared in a tile (let's say that 7 instances of foo would be 35 interfaces), I reach the maximum number of chanends, even though I do not have any of the interfaces instantiated in a client side (so never any will be used).

Is there any option for the compiler, or is possible to do somehow or is it planned to implement the feature that the compiler assigns tile chanends just to interfaces instantiated in two ends?.

I understand that I could define the number of items in the array as an argument...

Code: Select all

void foo(interface bar server i_bar[n], int n);
But this does not seem like an elegant and straightforward way of defining a function of a library, specially when several arrays of interfaces are taken.

Thanks a lot!
:)


User avatar
xsamc
Active Member
Posts: 55
Joined: Fri Mar 04, 2011 3:38 pm

Post by xsamc »

Hi atena,
atena wrote: From all the interfaces available within the arrays, not always all interfaces are instantiated in both ends. However, as soon as I have 32 Interfaces declared in a tile (let's say that 7 instances of foo would be 35 interfaces), I reach the maximum number of chanends, even though I do not have any of the interfaces instantiated in a client side (so never any will be used).

Is there any option for the compiler, or is possible to do somehow or is it planned to implement the feature that the compiler assigns tile chanends just to interfaces instantiated in two ends?.
This appears to be a limitation for the case where the server and clients run on separate cores (and/or tiles), so I have raised a bug internally about this.

However, if your application allows the task on one side of the interface to be distributed you should see a reduction in the number of channel ends used by the interfaces. Here is a simple test case which shows the channel end saving available:

Code: Select all

typedef interface bar {
  void foobar();
} bar;

[[distributable]] void foo(interface bar server i_bar[n], unsigned n) {
  while (1) {
    select {
      case i_bar[int i].foobar():
        break;
    }
  }
}

void fooclient(interface bar client i_bar) {
  i_bar.foobar();
}

int main() {
  interface bar my_bars[20];

  par {
    [[distribute]] foo(my_bars, 20);
    fooclient(my_bars[0]);
    fooclient(my_bars[1]);
    fooclient(my_bars[2]);
    fooclient(my_bars[3]);
  }
}

Code: Select all

Constraint check for tile[0]:
  Cores available:            8,   used:          4 .  OKAY
  Timers available:          10,   used:          4 .  OKAY
  Chanends available:        32,   used:          0 .  OKAY
  Memory available:       262144,   used:       5112 .  OKAY
    (Stack: 1644, Code: 2992, Data: 476)
Constraints checks PASSED.
If the above code is modified such that foo is is no longer distributable:

Code: Select all

Constraint check for tile[0]:
  Cores available:            8,   used:          5 .  OKAY
  Timers available:          10,   used:          5 .  OKAY
  Chanends available:        32,   used:         24 .  OKAY
  Memory available:       262144,   used:       2912 .  OKAY
    (Stack: 796, Code: 1636, Data: 480)
Constraints checks PASSED.
atena wrote:

Code: Select all

void foo(interface bar server i_bar[n], int n);
As far as I know passing the array bounds as you suggested will allow the compiler to eliminate certain bounds checks, but will not alter how many channel ends are consumed by interfaces.

Cheers,
Sam