Alexandre Garnier
email: alexandre.garnier@mines-nantes.fr

Jean-Marc Menaud
email: jean-marc.menaud@mines-nantes.fr

Nicolas Montavont
email: nicolas.montavont@telecom-bretagne.eu

Bringing Complex Event Processing into Multitree Modelling of Sensors

Keywords: sensor networks, domain-specific languages, complex event processing

The recent advances in the Internet of Things allow deploying a large variety of applications for smart cities, home automation or the industry of the future. These applications generate a large amount of data that can be challenging to manage; identifying and parsing this data become a prominent problem. In order to address this issue, we propose a multitree model for the sensor representation which matches the need for heterogeneous applications and user support. From there, we define a complex event processor based on a new language and grammar, in order to filter and identify user specific events. We show that we considerably reduce the size of queries by focusing on end-users knowledges as semantics for data streams.

Introduction

From home automation to smart cities, from amateur weather stations to large deployments of smart power meters in datacenters, Internet of Things (IoT) applications target more and more end-users every day. The link between these users and the IoT is usually provided by applications deployed over a sensor network. A recurring problem concerning sensor networks is the heterogeneity, not only of sensors, but also of the protocols used to access them, often characterized by their low bandwidth and poor reliability. To address this issue, the notion of data streams has emerged, leading to a change of paradigm around data parsing, from traditional DataBase Management Systems (DBMS) to Complex Event Processing (CEP). Instead of processing stored persistent data through volatile queries, CEP parses volatile data stream as it comes through persistent queries. However, parsing the raw data issued from sensors remains a complex task. This is due to the endless nature of the data stream and its growing heterogeneity, which reflects the variety of networked things. In order to address this issue, ideally the data has to be adapted to the user's knowledge.

Given that the number of users to consider grows with the IoT coverage, the ability to provide a meaningful access to the data to each user is a prominent problem. If CEP alone is able to notify specific users with data they are interested in, it does not allow to pre-identify these data. To leverage this gap, some kind of semantics, or context, can be attached to the data, in order to assist users when identifying the information they need. To this end, various tracks have been followed, from ontology-based enrichment to context-aware solutions. While ontology-based solutions tend to be harsh to manage for non-expert end-users and do not directly address their needs, context-aware solutions usually lack interoperability between different user contexts. A good compromise could be to provide a cross-context modelling of the data. Such a model would provide a defining frame to the semantical enrichment, while avoiding context partitioning. In order to fully provide to users a simple yet effective access to the data, CEP should be merged with such a modelling of the data.

Our previous work, SensorScript [START_REF] Garnier | Sensorscript: a domain-specific language for sensor networks[END_REF], aimed at providing a cross-context modelling of the data. In this paper, we propose to enhance it with a complex event processor, addressable through a new Domain-Specific Language (DSL). The DSL focuses on pre-identified uses and their combinations, relying on end-users oriented knowledge. This allows to reduce lengths of queries an end-user can express as they are able to manipulate nothing more than what he considers to be relevant information. Moreover, decision making can be automated in order to address actuators specific features in addition to sensors data gathering.

The remainder of the paper is organized as follows. Section 2 studies existing work about data semantics and CEP. In section 3 we draw up the motivation for integrating CEP with SensorScript. Sections 4 and 5 introduce the model and the language which ensure complex event processing. Section 6 evaluates the language concision and the underlying query management through a demonstration scenario. Finally, section 7 concludes by presenting future work.

Related Work

Data identification has been a prominent track of research over the years.We can divide the existing work into two categories: data semantical enrichment on one hand; context aware data stream mining on the other hand. Several publications about context awareness for the IoT are discussed in [START_REF] Perera | Context aware computing for the internet of things: A survey[END_REF]. In this paper we will focus on solutions which provide real-time processing of the data stream, as it is a strong requirement for complex event processors.

In [START_REF] Teymourian | Enabling knowledge-based complex event processing[END_REF] data semantics are provided by a separated knowledge base, which is a Resource Description Framework [START_REF] Klyne | Resource description framework (RDF): Concepts and abstract syntax[END_REF] (RDF) store. Thus event queries mix raw events extracted from the data stream and background knowledge retrieved from the knowledge base. That allows to establish relationships between the raw events. RDF knowledge base access is done through SPARQL [20] queries. This inevitably leads to hybrid queries, which mix SPARQL syntax with complex event paradigm. Use of such semantically enriched complex events is addressed in [START_REF] Textor | An architecture for semantically enriched data stream mining[END_REF]. It relies on the notion of event stream from which raw data is pulled then pushed back after semantical enrichment and event composition. Furthermore, a partitioning of enriched data stream mining operators is proposed for both CEP (e.g. filters or aggregators) and knowledge operators. SCONSTREAM [START_REF] Kwon | Sconstream: A spatial context stream processing system[END_REF] aims at providing spatial enrichment over the data for the specific case of users tracking in home automation. Queries continually parse the raw data to generate spatialized events when triggered. UbiQuSE [START_REF] Shaeib | A framework for real-time context provision in ubiquitous sensing environments[END_REF] proposes a more generic contextual framework for data mining queries. It relies on XML formalism for context-enriched data. Thus it uses XQuery [START_REF] Boag | XQuery 1.0: An XML query language[END_REF] to express queries that address both real-time and historical data querying. This broadens the use of the DBMS, as it stores both contextual and historical data. These two solutions however rely on pre-existing solutions to bundle both data mining (being real-time or periodic) and context-awareness, which leads to hybrid querying over the data. COPAL [START_REF] Li | Copal: An adaptive approach to context provisioning[END_REF] aims at providing a DSL to broaden the notion of context from sole location to handle processing environments in the case of distributed processing. This DSL provides a complex event processor in order to compose events through a declarative, and quite verbose, developer-centric syntax, in the sense that a user has to learn the underlying model before composing events. A common issue of these solutions remains in the context storage, generally based on a decoupled DBMS, which impacts the simplicity of queries. The runtime additional cost of addressing the DBMS and couple its information with the raw data is addressed by none of these publications.

Concerning CEP languages, other contributions mainly aimed at adapting Structured Query Languages (SQL) to manage data streams and event composition. CQL [START_REF] Arasu | Cql: A language for continuous queries over streams and relations[END_REF] is one of the first to do so. The change of paradigm from relational databases to complex event processing focuses on the notion of a relation. A relation is addressed in the from clause, like tables in SQL, and mapped over time windows to a finite set of data from. Other than time windows, partitioned windows can also be expressed, providing a partition over the data stream similar to the SQL group by clause. TinyDB [START_REF] Madden | Tinydb: an acquisitional query processing system for sensor networks[END_REF] provides time windows with a dedicated additional clause rather than a mapping over data stream. It also allows to specify a recovery rate for queries execution, jeopardizing efficiency as there is no guarantee that the data will be updated at at least the same rate of the accesses defined in queries. Aiming at providing more flexibility over windows specification, Esper [START_REF]EsperTech[END_REF] provides the notion of pattern which orchestrates both time windows and data filtering with boolean operators. WildCAT [START_REF] David | Wildcat: a generic framework for context-aware applications[END_REF] aims at coupling Esper Processing Language (EPL) with data context awareness through hierarchical contexts definition. However, this semantical enrichment of data operates as on overlay to Esper rather than being fully integrated within EPL.

Another track focused on declarative event specification. AmbientTalk [START_REF] Van Cutsem | Ambienttalk: object-oriented event-driven programming in mobile ad hoc networks[END_REF] uses this concept for the actors within mobile ad-hoc networks, as a mean to leverage the problematics specific to these infrastructures. TESLA [START_REF] Cugola | Tesla: a formally defined event specification language[END_REF] formalizes an event specification language. Following AmbientTalk, REScala [START_REF] Salvaneschi | Rescala: Bridging between object-oriented and functional style in reactive applications[END_REF] and EventCJ [START_REF] Kamina | Eventcj: a context-oriented programming language with declarative event-based context transition[END_REF] integrate such a formalism within object-oriented and functional programming. If these languages depart from traditional SQL, they however concentrate on addressing a larger scope rather than simplifying their syntax.

Motivation

SensorScript was based on a previous work: btrScript [START_REF] Pottier | Btrscript: a safe management system for virtualized data center[END_REF]. btrScript is a datacenter monitoring DSL inspired by XPath [START_REF] Clark | Xml path language (xpath) version 1[END_REF], in particular its queries which allow implicit pathfinding within a tree. Indeed the DSL is backed to two static trees to address both virtualized and physical aspects of a modern datacenter. In [START_REF] Garnier | Sensorscript: a domain-specific language for sensor networks[END_REF], we altered the underlying model to manage any number of configurable intricated trees, which allows SensorScript to address the diversity of sensor networks. The trees intrication of the model will be detailed in section 4.

The benefits of such a modelling are two-fold. On one hand it offers a good semanticization over the data by integrating it within tree contexts. On the other hand, queries remain concise as the model still relies on trees. Hence, we consider these features make SensorScript a strong candidate to be integrated within a complex event processor, as existing CEP languages suffer from verbose queries. This led us to deeply alter SensorScript data and query management, and to rethink key components of the DSL grammar.

Model

The model consists of two parts, which are the data modelling and the complex event processor. The data modelling consists on a multitree modelling of the data in which each tree corresponds to an end-user field of expertise, or a context. Figure 1 illustrates a multitree model with five different contexts. These contexts revolve around a conference site, with lighting monitoring and automation on one hand, and presentations' affluence tracking system on the other hand. These use cases are described in more detail through some examples in section 6.

Fig. 1. Example of a multitree model

To set up complex event processing, we propose to change the paradigm on which is based traditional data management. Instead of considering the data as persistent, we assume data streams on which queries are considered persistent. These queries must be constantly aware of any data update. To achieve that, a naive solution would be to rely on a periodic queries-executing process. This is however unsatisfactory because of higher costs in terms of both efficiency and responsiveness, according to the data stream rate. More realistically, both problems will happen at different times, due to the various underlying networks which are not all reliable, and the various number of queries impacting their execution time. Hence, the query model must react dynamically to data changes. We lean on the multitree model to leverage data accessibility. The hierarchy of nodes within the multitree can and will be accessed through the queries, as it provides meaningful information about contexts, therefore users specific knowledges. As a matter of fact, queries results are updated on real time with the data stream, but also with changes of the multitree structure. Thus the multitree sets a semantical structure down. Queries rely on these semantics in order to access nodes based on the constitutive contexts information of the multitree model. To achieve that, we propose the query object model as illustrated in the UML class diagram of figure 2.

In our query object model, a query consists of three main concepts, which are the node selection, on which can be expressed a condition, and the optional access to selected node attributes or methods.

Selections

An arbitrary amount of sub-selections can be specified, as well as conditions optionally filter the nodes in each selection or sub-selection. Considering that nodes can be added, moved, removed, and conditions on them can change, selections will evolve with each change impacting its nodes.

Conditions

Conditions allow to filter the selected nodes. Two kinds of conditions can be expressed:

conditions on attributes (specified by name): for each node of the selection, a comparison is done either between an access and a constant, or between two accesses over the node; conditions on connected nodes (specified by type): for each node of the selection, a boolean set operation is done on all the nodes of the given type that are accessible, upwards or downwards, from this node; for instance, we can restrict the selection of all sockets to the set of sockets with no powermeter.

Accesses

Accesses are made on each node of the selection, and can be delivered as is or aggregated (thus the Aggregation access inheritance).

Language

The main objective of the SensorScript language is to allow users to express CEP queries about their own field of expertise, regardless of the complexity of the whole underlying multitree model. As we saw in section 2, existing CEP DSL derive from SQL, thus require users to know more of the underlying model than what should be needed. In contrast, SensorScript comes with a language which leans on the multitree model and takes advantage of the relations between its nodes to provide implicit connections among them, regardless of the distance separating them in the model. As we want to keep the language as concise as possible, we choose to use character operators rather than english words based syntax, which we hope significantly reduces the verbosity of queries. Naturally, the language reflects the selection, access and condition concepts constituting a query as presented in section 4. It is essential however to keep the expression of these three concepts as simple as possible. Considering these points, we propose a simplified grammar of the language in listing 1. We will go through the grammar rule by rule, following the nonterminals as they occur within rules. Rule 1 reflects that a query is either a selection or an access (simple or aggregated) over a selection.

Selection

The second rule shows that sub-selections over a selection are expressed by the slash operator between super and sub-selections. Selections are expressed either on node types or node names. For this reason, not only both names and types are unique, but also a name cannot be equal to a type. Considering a sensor network modelled with figure 1, the query listing the breakers of room 42, for instance, would be: room42/breaker

Condition

Rule 2 in listing 1 also introduces the expression of conditions, within braces operators, over selections. As shown in rule 4, conditions are either simple, consisting of comparisons on accesses, or composed of sub-conditions by boolean operators.

Besides traditional and and or operators, we introduce here the sequence operator ";", so that the condition <selection>{A;B} ensures that conditions A then B are met on nodes of the selection. That does not mean that B has to match after A is satisfied, but that, whether or not B was already satisfied when A matches, B must be checked chronogically after A matches for the condition to be met.

Another aspect of time management appears with time conditions, which are simply conditions checked over a duration of time, both of them expressed between parentheses and separated by a comma.

As an example, we consider that one wants to detect the room 42 powermeters that go through an electrical overload. This can be described as the powermeters that have a power consumption that outnumbers their capacity just before it drops to zero, which can be expressed with this query: room42 / powermeter { power > capacity ; power = 0}

As preventing an electrical overload seems to be a better solution, one could create an alert of when a powermeter is soon to be overloaded, for instance when its power consumption remains close to its capacity (with a minimum charge of 90%) for at least one hour: room42 / powermeter {( power > capacity * 0.9 , '1 h ')}

Access

Accesses are done on each node of a selection, through the dot operator. The access of a query occurs on two occasions on runtime:

when a node is added to the selection, access on it occurs systematically; for a node already in the selection, each node update that affects the access will trigger it.

Rules 3 and 5 in listing 1 show that they exist several possible accesses on nodes:

Attribute access for each node of a selection, the query will wait for the given attribute to be updated. For instance, to be notified of each power update from powermeters of room 42: room42/powermeter.power

Constant access this access allows to express constants, which is mostly useful for conditional expressions. As shown in rule 4, accesses within conditions are expressed without the dot operator. Considering our previous example, this corresponds to the zero in this query:

room42/powermeter{power > capacity; power = 0}

Method access for each node of a selection, the query will recall the method for each node update that might affect the method result. This will exclusively happen for method with parameters that correspond to attribute accesses. For methods with no parameter or only constant parameters, accesses are only provided when nodes are added to the selection and for these nodes only. Two types of methods exist:

simple methods: similar to attributes accesses, they are called separately for each node of the selection. For instance, this is the get method, which is equivalent to an attribute access: /room42/powermeter.get(power) aggregation methods: on the contrary, aggregation methods provide a computation which occur on all nodes from the selection to produce one result only; an update on one node of the selection, as well as changes of the selection itself, will trigger the method to be called. As an example, let's consider that one wants to access the total consumption from room 42 powermeters:

room42/powermeter.sum(power)

Foreach

A particular aggregation use case allows to partition the selection to provide a behavior similar to the group by clause in MySQL. This is what we call the foreach aggregation method access, expressed by the colon operator in rule 1.

To explain how it is expressed, we will consider this example , and its equivalent in SQL:

SensorScript SQL room42/breaker:powermeter.sum(power) SELECT sum(powermeter.power) FROM breaker, powermeter WHERE breaker.room = 42 AND powermeter.brId = breaker.id GROUP BY breaker.id

We see here two selections around the colon operator, which are breakers from room 42 for the first one, powermeters for the second one. Besides, the sum method is called on the power attribute from powermeters. De facto, this query will follow power updates for each room 42 powermeter. But rather than summing the whole power consumption of the room, it will sum the power consumption for each breaker accessible from the room 42, considering sockets within a same room are attached to different breakers.

So, if we consider a query of the form A:B.method(access), considering that A and B are selections, this means that for each node N from the selection A, the specified aggregation method will be called on nodes from selection B accessible from N (or the nodes corresponding to the N/B).

The difference in the concept's name with SQL is to reflect the way it is expressed and avoid confusion: the group by clause precedes an attribute, the foreach operator follows a node selection.

Evaluation

This section proposes to evaluate the language concision through some examples over the model from figure 1 and compare them with similar examples from the literature. Then we propose a scenario which reflects a more complex yet realistic use of the language. Both approaches focus only on syntactic concision of the language, performance evaluation will be subject to future work. Futhermore, we will specifically look at timed conditions management as they bring an additional constraint over the model dynamicity. Finally, we will highlight the limitations of SensorScript in terms of features, compared to other CEP languages.

Comparison with CQL

In the model from figure 1, more specifically around the track, speaker and participant contexts, we consider a conference for which name tags distributed to every attendee embed an RFID chip. For each presentation, they are invited to check in by swiping their name tag in an RFID reader. Speakers (which is a role that an attendee assumes for a presentation) also check in when beginning their presentation. Each room of the conference has its own RFID reader. Technically, the data stream is flowing with the presence of attendees in any of the conference rooms.

To keep things as simple as possible, we concentrate here on the three aforementioned contexts:

the participant context, for attendees who attend a presentation; the speaker contexts, for the attendee who holds a presentation; the track contexts, that reflects the fact that presentations are part of a track of the conference.

These three contexts are directly inspired from the example of CQL [START_REF] Arasu | Cql: A language for continuous queries over streams and relations[END_REF]. This example considered an auction system, for which we propose the mapping table 1 in order to stick to our conference tracking system. Table 2 gives a comparison between SensorScript and CQL queries based on the aforementioned mapping.

1. The first query allows to select presentations that occur after noon. It is conceptually very similar to the CQL query, as the condition between braces corresponds to the one declared in the where clause. 2. This second query aims at maintaining a running count of attendees to tracks 1 and 2 over the last hour. There is an important difference here as time windows can only be specified within conditions in SensorScript. This results in two conditions specified over the two sub-selections of the whole selection.

3. With this query we want to maintain a list of the current presentations.

The main difference here is that SensorScript relies on attributes updated with the data stream over the nodes of the multitree, where CQL backs to table-like streams to manage the presentation state (ongoing or over ).

4. Given that we want here to list the present attendees, we only need to add a sub-selection to the previous query with SensorScript, considering that a present attendee is an attendee that checked in a current presentation. On the other hand, CQL proposes a whole new, though significantly longer, query, based once again on streams that reflect presence or absence of attendees.

5. As presentations can be rescheduled during the conference, we consider now that speakers check-ins affect directly the state of presentations. This allows us to get a list of non-keynote presentations, as we can follow the presentations that started then stopped in a window range of less than 35 minutes.

We see here that the pathfinding mechanism of the language allows to get rid of any explicit join condition. 6. This last query keeps the age of the youngest speaker for completed presentations. An interesting point here relies on the multitree structure. As we saw in figure 1, the graph follows two routes from attendee to attendance, depending on whether the attendee is the speaker or assists to the considered presentation. In fact, the multitree allows partially ordered sets (or posets) in the graph, as long as absolute order can be decided between every couple of types from a poset. Actually, we rely on this property here to get the list of speakers. When following the orientation of connections between types, the nearest matching nodes are selected. Therefore, for presentations attendee nodes, this is the speaker. That said, if one wants to look at the age of the youngest audience member of completed presentations, this can be done with the following query, as attendance nearest attendee nodes are accessed through the participant context rather than the speaker context:

presentation{status='over'}/attendance/attendee.min(age)

In comparison, CQL requires both a nested condition and an explicit join.

As we can see, SensorScript expressions minimize the concepts that are specific to the language. In fact, selections, accesses and conditions are specified by operators rather than english words. Moreover, it simplifies multi-stream selections based on the implicit link provided between nodes by the multitree, compared to union specifications of SQL. Finally, conditions and timed conditions are expressed the same way, as the language was designed to implement them, whereas CQL introduces a new syntax dedicated to time windows.

Rooms lighting scenario

We propose here to consider the whole model from figure 1 in order to orchestrate all the sensors, aiming at automating the conference rooms lighting management. These different sensors allow to monitor light, participants presence and power consumption. The room lighting management addresses a typical problematic of home automation, which brings our example closer to both [START_REF] Textor | An architecture for semantically enriched data stream mining[END_REF] and [START_REF] Li | Copal: An adaptive approach to context provisioning[END_REF] examples. We also consider that blinds and powermeters are equipped with actuators. This will allow us to illustrate SensorScript's actions specification in order to address functions of these actuators.

In this scenario we will consider that ambient light of the conference has to be adapted according to several concerns:

-First of all, to save energy we would like the lighting of room to automatically turn off when all attendees have left it:

/ room {! has ( attendee )}/ lighting / powermeter . turnoff ()

We see in the model that two paths exist between the room and attendee types. However, only one condition is required here. In fact, on one hand, if a speaker is found using the shortest path, the condition is false without having to check the assistance using the longer path. On the other hand, if the room has no speaker but still some people in the audience, listing these attendees will be the only path existing within the model, therefore it will be the shortest one. This saves us having to express and test the two different accesses within the condition. -Second, for rooms with open blinds, when the daylight (measured by an outside light sensor named daylight for each room) falls below a certain threshold, we want the blinds to close and, if the room is not empty, the inside light to turn on. This is provided by the following two queries: As we saw, actuators functions are called as methods on nodes within the language. The method specification is provided through inheritance over the Node class in the system, which implements the multitree nodes. For instance, listing 2 illustrates the way to specify the open method for blinds. The system is able to detect classes that extend the Node class, which allows it to use these classes to instantiate according typed nodes, blinds in this example.

Limitations

CQL [START_REF] Arasu | Cql: A language for continuous queries over streams and relations[END_REF], TinyDB [START_REF] Madden | Tinydb: an acquisitional query processing system for sensor networks[END_REF] and Esper [START_REF]EsperTech[END_REF] take advantage of SQL to address both dynamic and persistent data. Considering SensorScript is designed over data streams only and ensures real-time processing of data, we could not afford to keep a history over the data. In fact, even timed conditions do not require a history to be checked. As we only have to make sure that the condition holds for the specified time, this is the unique information to keep during the lifetime of the condition, which is also discarded as soon as the condition is unsatisfied or the time is over. However, we do not aim at replacing traditional DBMS, that can be used in parallel, whether storing the whole data stream or data prefiltered by SensorScript.

Languages as AmbientTalk [START_REF] Van Cutsem | Ambienttalk: object-oriented event-driven programming in mobile ad hoc networks[END_REF], REScala [START_REF] Salvaneschi | Rescala: Bridging between object-oriented and functional style in reactive applications[END_REF] or EventCJ [START_REF] Kamina | Eventcj: a context-oriented programming language with declarative event-based context transition[END_REF] aim at integrating event specification into existing programming paradigms. In this sense, their scope extends far beyond the one studied here, as we focus on the multitree only as the underlying model of the language. Nevertheless this limitation is what gives SensorScript its concise language based on implicit model parsing.

Conclusions and Future Work

We presented here the evolution of SensorScript towards a language for complex event processing dedicated to sensor networks. While the model mainly relies on previous works, we highlighted how the new language builds on the multitree in order to provide complex event processing mechanisms. We are able to balance the syntactic concision of the language with a real-time complex event processor for sensor networks. By providing flexible selections over the nodes, with the possibility to filter them on complex conditions, possibly over a time window, we offer a strong alternative to traditional SQL used in the literature. Moreover, SensorScript does not focus only on data access. In fact it provides the possibility to widen the scope of the methods accessible on nodes to other features than sensors monitoring, including but not limited to addressing actuators functions. Finally we showed that SensorScript is able to address examples proposed in the literature, with simpler results than SQL, while highlighting its limitations, especially on history management. Future works will focus on deploying SensorScript over a sensor network spread over two distant sites. This will allow us to test both scalability and performance. Another lead would focus on interfacing with a traditional DBMS in order to integrate history management.

Fig. 2 .

 2 Fig. 2. Query object model

Listing 1 . 3 :→ SimpleAccess | AggregationMethod 4 : 5 : 6 : 7 : 8 :

 1345678 SensorScript simplified grammar 1: Query → Selection (.Access )? | Selection :Selection .AggregationMethod 2: Selection → AtomicSelection ({Condition })?(/Selection )? Access Condition → SimpleAccess Comparator SimpleAccess | Condition BooleanOperator Condition | (Condition , Duration ) SimpleAccess → Attribute | SimpleMethod | Constant Comparator → = | != | < | > | <= | >= BooleanOperator → & | | | ; AtomicSelection → NodeName | NodeType Non-terminal symbols Grammar description operators Terminal symbols

Listing 2 .

 2 Action specification example public class Blinds extends Node { [...] @SensorScriptMethod public boolean open () { // call to actuator switch to open the blinds } }

Table 1 .

 1 Mapping to CQL example

	Conference attendance monitoring model Auction system model
	Attendee	User
	Presentation	Auction
	Attendance	Bid
	Country	U.S. state
	Participant context	Bidding context
	Speaker context	Seller context
	Track context	Auction context

Table 2 .

 2 Comparison with CQL

	SensorScript	CQL
	1. presentation{starttime > '12:00'} Select * From Ongoing
		Where starttime > '12:00'
	2. track{name.in('tr1', 'tr2')}/	Select Count(*)
	attendance{checkintime >	From attendance[Range 1 Hour]
	now() -3600}.sum(1)	Where trackname In ('tr1', 'tr2')
	3. presentation{starttime +	Select * From Ongoing
	duration > now()}	Where pres_id Not In
		(Select * From Over)
	4. presentation{startime +	Select name, state From Present
	duration > now()}/attendee	[Partition By attendee_id Rows 1]
		Where attendee_id Not In
		(Select * From Absent)
	5. presentation{(status='ongoing' ;	Select Istream(Over.pres_id)
	status='over', '35 min')}	From Over[Now],
		Ongoing[Range 35 Min] Where
		Over.pres_id = Ongoing.pres_id
	6. presentation{status='over'}/	Select Istream(Over.pres_it,
	attendee.min(age)	A.age) From Over[Now],
		(Select attendee_id, age
		From attendee)
		[Partition by pres_id Rows 1]
		as A Where Over.pres_id =
		A.pres_id

  As a non-empty room is a room bound to at least one attendee, it is more efficient here to use implicit filtering on sub-selections (the /attendee/room/ part of the query) rather than an explicit condition on the rooms. -As ambient light, i.e. the light measured within a room, can incommode the readability of projected slides during a presentation, the following two queries propose to close the blinds, if open, and turn off the lights, if required, when a presentation starts:

	daylight { light < out_threshold }/ blinds . close ()
	daylight { light < out_threshold }/ attendee / room / lighting /
	powermeter . turnon ()
	presentation { status = ' ongoing ' ; status = ' over '}/
	daylight { light > out_threshold }/ blinds . open ()
	presentation { status = ' ongoing ' ; status = ' over '}/
	daylight { light <= out_threshold }/ lighting /
	powermeter . turnon ()

presentation { status = ' scheduled ' ; status = ' ongoing '}/ blinds { status = ' closed '}. close () presentation { status = ' scheduled ' ; status = ' ongoing '}/ lighting / powermeter { status = 'on '}. turnoff ()

-Finally, we want the blinds to open or the light to turn on, according to daylight, when a presentation is over:


Islam Alyafawi

Arnaud Durand
email: arnaud.durand@unifr.ch

Torsten Braun
email: |braun@inf.unibe.ch

High-Performance Wideband SDR Channelizers

Keywords: SDR, CPU, GPU, Channelizer

The essential process to analyze signals from multicarrier communication systems is to isolate independent communication channels using a channelizer. To implement a channelizer in software-defined radio systems, the Polyphase Filterbank (PFB) is commonly used. For real-time applications, the PFB has to process the digitized signal faster or equal to its sampling rate. Depending on the underlying hardware, PFB can run on a CPU, a Graphical Processing Unit (GPU), or even a Field-Programmable Gate Arrays (FPGA). CPUs and GPUs are more reconfigurable and scalable platforms than FPGAs. In this paper, we optimize an existing implementation of a CPU-based channelizer and implement a novel GPU-based channelizer. Our proposed solutions deliver an overall improvement of 30% for the CPU optimization on Intel Core i7-4790 @ 3.60 GHz, and a 3.2-fold improvement for the GPU implementation on AMD R9 290, when compared to the original CPU-based implementation.

Introduction

Different wired/wireless systems, such as the Global System for Mobile Communications (GSM), use frequency-division multiplexing (FDM) techniques [START_REF] Harris | Multirate Signal Processing for Communication Systems[END_REF]. In FDM-based systems, the signal is divided into multiple channels without crosssynchronization among themselves. In [START_REF] Alyafawi | Real-time passive capturing of the gsm radio[END_REF], we developed a single-band passive receiver that can capture, decode, and parse uplink messages of different GSM Mobile Devices (MDs). The proposed receiver is implemented as a GNURadio (GR) module with definite input and output interfaces. The output from multiple receivers (MD identity and received signal power) was sent to a centralized system to perform the localization process as described in [START_REF] Alyafawi | Critical issues of centralized and cloudified lte-fdd radio access networks[END_REF]. However, since GSM MDs in a certain area may connect to multiple GSM Base Transceiver Stations (BTSs) operating at different frequencies, it is required to support the proposed Software-Defined Radio (SDR) receiver with wideband capturing capabilities. To do so, we use a channelizer, which splits the wideband spectrum into a set of independent channels fed to different instances of the single-band receiver as shown in Fig. 1. Fig. 1. Architecture of a wireless localization system using the wideband GSM receiver.

Polyphase Filterbanks (PFB) channelizers are powerful tools that (i) split the wideband signal into equispaced channels and (ii) filter the split channels with a given filter. The channelizer performance varies based on the underlying processing hardware architecture. While FPGA-based approaches can provide the required processing performance, they lack the run-time flexibility of GPPbased approaches [START_REF] Awan | Fpga implementation analysis of polyphase channelizer performing sample rate change required for both matched filtering and channel frequency spacing[END_REF]. The authors in [START_REF] Adhinarayanan | Wideband channelization for software-defined radio via mobile graphics processors[END_REF][START_REF] Adhinarayanan | On the performance and energy efficiency of fpgas and gpus for polyphase channelization[END_REF][START_REF] Del Mundo | Accelerating fast fourier transform for wideband channelization[END_REF][START_REF] Kim | Implementation of a high-throughput lowlatency polyphase channelizer on gpus[END_REF] show the possibility to perform a PFB channelizer with a GPU underlying processing unit. However, these solutions are (i) not implemented as GR modules, (ii) not provided as an open-source and (iii) not optimized with respect to throughput and latency for data transfer between system memory (RAM) and GPU memory.

The contribution of this paper is optimizing an existing GR CPU-based channelizer using advanced CPU instructions and implementation of a new highperformance GPU-based channelizer suited for GR (c.f., Sections 3 and 4). Our proposed solutions are provided as GR open-source modules [START_REF] Channelizer | [END_REF] with optimized data transfer between RAM and GPU memory. An evaluation of the proposed solutions is presented in Section 5.

Problem Formulation

Our focus is to improve the PFB channelizer performance as a GR module. The channelized streams can then be sent to a centralized or a distributed system for signal processing and data acquisition. Our solution starts by understanding the signal processing and conversions between the antenna and the processing machine holding the channelizer.

SDR Hardware

Our proposed solution is hardware agnostic and, hence, it is possible to use any SDR equipment from any vendor that meets the minimum performance requirements. The Universal Software Radio Peripheral (USRP) is a series of SDR-enabled devices [START_REF] Research | [END_REF]. We use a set of USRP N210 devices (we call them N210 for simplicity). A simplified architecture of the N210 is illustrated in Fig. 2. The received radio signal will be amplified before being converted from the High-Frequency (HF) to the Intermediate-Frequency (IF) band. Then, it will be filtered using a Low-Pass Filter (LPF) with a bandwidth up to 20 MHz. The filtered signal is digitized inside the Analog-to-Digital Converter (ADC), which has 14-bit precision for each In-phase and Quadratic (I/Q) samples. The ADC digitizes the signal with a fixed sampling rate equal to 100 Msps (Mega samples per second). The FPGA changes the data to 32-bit samples when configured in 16-bit mode (16 bit I and 16 bit Q). The UHD driver is used to control I/O communication between the USRP and the host computer [22]. It is configured to transfer up to 25 Msps in 16-bit mode over a Gigabit Ethernet (GbE) interface.

The UHD driver converts sampled signals obtained from the USRP to IEEE 754 floating point numbers and store them in the host memory.

Wideband Channelizer

GR is an open-source framework to build SDR systems. Radio samples are typed gr complex in GR, but are in fact only a redefinition of the C/C++ std :: complex data type. Complex numbers are represented as two consecutive singleprecision Floating-Point Units (FPUs), thus taking 64 bits. The default GR PFB channelizer makes use of the host CPU to process the entire bandwidth signals, which can take advantage of CPU-specific SIMD (Single Instruction Multiple Data) operations. Without any up-/down sampling operations, the overall output sample rate of a PFB channelizer is equal input sample rate. Nevertheless, the available processing resources will reach their limits with the increasing width of the channelized spectrum. Hence, there is a need for alternative optimized (or newly implemented) PFB solutions within the same processing platform [START_REF] Durand | [END_REF].

GPUs are fine grain SIMD processing units suited for general-purpose processing with a relatively low cost compared to other specialized architectures [START_REF] Plishker | Applying graphics processor acceleration in a software defined radio prototyping environment[END_REF]. GPUs contain a large number of computing units. Hence, they can be used to implement a high-performance channelizer. There are several technologies available to realize GPUs, such as the CUDA programming model or the OpenCL framework [START_REF] Wilt | The CUDA Handbook: A Comprehensive Guide to GPU Programming[END_REF]. However, to integrate such solutions with the GR framework, it is mandatory to implement the channelizer as a GR module. An essential requirement is the ability to transfer data between CPU (where GR works) and GPU (where the channelizer can be implemented) at high bandwidth and low latency. As shown in Fig. 2, existing communication methods that transfer data through CPU memory to the GPU might be used. Additional to the original data transfer between the FPGA and system memory (RAM), data must cross the PCI Express (PCIe) switch twice between the RAM and GPU memory.

Polyphase FilterBank Channelizer

A PFB channelizer is an efficient technique for splitting a signal into equallyspaced channels [START_REF] Harris | Multirate Signal Processing for Communication Systems[END_REF]. A PFB is mainly composed of two main modules: M FIR (Finite Impulse Response) filters (the filterbank) and an M -point FFT (Fast Fourier Transform). A basic implementation of the PFB channelizer is illustrated in Fig. 3, which represents the input with M FDM channels that exist in a single data stream and the resulting M Time Division Multiplexed (TDM) output channels. The fundamental theory of polyphase filters is the polyphase decomposition [START_REF] Madisetti | The Digital Signal Processing Handbook[END_REF]. We discuss here the two principal components of the decomposition process.

FIR filters: are digital filters with a finite impulse response. The transfer function of FIR filter samples is expressed in Equation 1.

f[n] = N -1 k=0 h[k]x[n -k] (1)
N is the number of FIR filter coefficients (known as filter taps), x[k] are FIR filter input samples, h[k] are FIR filter coefficients and f[n] are FIR filtered samples. A Fast Fourier Transform (FFT) is a fast way to calculate the Discrete Fourier Transform (DFT) of a vector x. The FFT operation transforms the input signal from the time domain into the frequency domain. The M-point FFT transfer function is expressed in Equation 2.

y[k] = M -1 m=0 f[m]e -2πjmk/M (2) f[n]
is the input and y[k] is the output. The time it takes to evaluate an FFT on a computer depends mainly on the number of multiplications involved. FFT only needs M log 2 (M ) multiplications.

H M-1 M point FFT H 0 H 1 H 3 H 2 ... ... x(n) FDM TDM y 0 (n) y 1 (n) y 2 (n) y 3 (n) y M.1 (n) FIR filters f 1 (n) f 2 (n) f 3 (n) f M.1 (n) f 0 (n)
Fig. 3. PFB channelizer.

Enhanced CPU-based PFB

GR takes advantage of architecture-specific operations through the Vector Optimized Library of Kernels (VOLK) machine [START_REF] Volk | [END_REF]. The VOLK machine is a collection of GR libraries for arithmetic-intensive computations. Most of the provided VOLK implementations are using x86 SIMD instructions, which enable the same instruction to be performed on multiple input data and produce several results (vector output) in one step. The FFT operations are computed through the fftw3 library [START_REF][END_REF]. This open source library takes advantage of modern CPU architectures by making use of specific SIMD operations. As we consider this library to be optimal for CPU usage when used correctly, we will not consider further FFT optimizations. FIR filters are accumulators that perform a lot of multiply-accumulate operations. Thus, the PFB channelizer relies heavily on the VOLK multiply-and-add routine and most of the CPU cycles are spent inside this function [START_REF] Rondeau | Designing anaylsis and synthesis filterbanks in gnu radio[END_REF]. The fastest multiply-and-add routine available in the VOLK machine for our CPU (Intel Haswell) is volk 32fc 32f dot prod 32fc a avx using the Advanced Vector Extensions (AVX) instruction set [START_REF] Lomont | Introduction to intel advanced vector extensions[END_REF]. In the following, we present a set of optimizations by the available AVX PFB implementation.

Memory Alignment: CPUs access memory in chunks. Depending on the memory access granularity, a CPU may retrieve data in 2, 4, 8, 16, 32-bytes chunks or even more. Depending on the particular instruction, it may or may not be allowed to load data from memory into registers using addresses not being multiple of the memory access granularity [START_REF] Corperation | Intel c++ compiler intrinsics reference[END_REF]. Indeed, if allowed, loading unaligned data requires more operations as the register must execute shifting and merging operations of different memory chunks. AVX are extensions to the x86 instruction set. They allow operations on 256-bit registers, enabling eight singleprecision floating point numbers to be stored side-by-side in the same register and processed simultaneously. AVX uses relaxed memory alignment requirements. It means that using unaligned data is allowed for most instructions, but this comes with a performance penalty. When allocating memory using malloc(), ...

$ $ $ $ $ $ $ $ $ $ $ 0 0 0 0 $ $ x9 x8 x7 x6 x5 x4 x3 x2 x1 x0 $ $ $ $ Input ... * * d_taps[1]

AVX-register AVX-register

Fig. 4. GR FIR taps alignment and AVX dot product.

compilers are in charge of the alignment, and we cannot assume that the returned address is aligned. However, it is possible to force alignment when desirable. GR provides such facility through the volk malloc() function [START_REF] Gnuradio | [END_REF]. Such a function allocates a slightly bigger amount of memory (desired size + granularity -1) and moves the pointer to the next aligned address. However, the FIR filters from the PFB channelizer cannot use this function because GR buffers are not necessarily aligned. Instead, GR generates a set of aligned taps d taps for each possible architecture alignment as shown in Fig. 4. In the illustrated example of Fig. 4, we have a FIR filter with a history of 10 samples h[0], ..., h [START_REF] Durand | [END_REF]. By measuring the alignment of the input samples, we can select the correctly aligned taps. For example, if the input register is aligned with two floats, GR will choose to multiply with d taps [START_REF] Adhinarayanan | On the performance and energy efficiency of fpgas and gpus for polyphase channelization[END_REF] (a set of taps aligned with two floats). $ indicates unaligned data and x[0], .., x [START_REF] Durand | [END_REF] are the input samples. GR performs SIMD operations on aligned data and non-SIMD operations on the remaining input samples. To avoid non-SIMD operations, one solution is to make the number of filter taps as a multiple of 8. Then, we can fill taps corresponding to unaligned data with zeros as shown in Fig. 4 (d taps [START_REF] Adhinarayanan | On the performance and energy efficiency of fpgas and gpus for polyphase channelization[END_REF]). We then consider the data aligned in GR buffers because zeros will discard unaligned input values.

Fused multiply-add (FMA) operations: FMA operations are AVX2 instructions to 128 and 256-bit Streaming SIMD Extensions (SSE) instructions [START_REF] Jain | The haswell microarchitecture -4th generation processor[END_REF] (AVX2 is an expansion of the AVX instruction set). AVX2 FMA operations are floating point operations similar to c ← (a * b) + c, which performs multiply and add in one step (c.f. Fig. 5). These operations are compatible with the GNU compiler collection. However, AVX performs (a * b) + c in two steps (first a * b, then + c). Benchmarks of pure multiply and accumulate operations on Intel Haswell CPUs show double performance using AVX2 FMA compared to AVX. The PFB implementation uses the product of complex and float vectors. This implementation requires some further operations like deinterleaving an input block of complex samples into M outputs. Better Pipelining: complex numbers are just two consecutive floats as defined in complex.h of the C standard library. From the previous example c ← c + (a * b), a is a complex number representing an input sample and b is an integer representing a FIR filter coefficient. Consider that a is a tuple of (r, qi): r is the in-phase part of a, q is the quadrature part of a, and i is the complex number √ -1. Complex arithmetic rules define a*b = (r + qi) * b = (r + qi) * (b + 0i) = (rb + qbi). As the GR FIR filters are not specifically designed for AVX operations, the coefficients are just stored as consecutive floats. Unfortunately, feeding 256-bit registers with consecutive floats is a costly process because it requires a for-loop operating over all input sample to perform the (r + qi) * b instructions. The best we can do is to create a more compatible layout of filter taps to benefit from AVX2-FMA operations. To do this we load ( mm256 loadu ps), unpack ( mm256 unpackXY ps) and then permute ( mm256 permute2f128) FIR coefficients before operations. The behavior of unpack does not allow to permute coefficients across 128-bit boundaries. This behavior is inherited directly from the legacy SSE unpack operation. However, by re-shuffling the taps during the creation of the PFB as illustrated in Fig. 6, we can create a layout that enables the taps to be in the right order when unpacked (without permutation). Then, we can perform four (r + qi) * b instructions in one step.

GPU-based PFB

We can make PFB processing faster by taking advantage of massively parallel architectures, such as GPUs [START_REF] Plishker | Applying graphics processor acceleration in a software defined radio prototyping environment[END_REF]. There are several technologies available to perform GPU processing. OpenCL is an open framework for heterogeneous computing [START_REF] Tsuchiyama | The OpenCL Programming Book[END_REF]. It is open by design and, therefore, best suited to the philosophy of GR. For this reason, we will implement a PFB channelizer using OpenCL. In our test setup, we use a discrete graphics card, meaning that the CPU and GPU do not share the same memory (c.f. Fig. 2). There are several techniques to transfer data between the CPU and GPU, with various transfer speeds [START_REF] Munshi | The opencl specification, version 1[END_REF]. However, when using physically shared memory between the GPU and CPU using fused architectures, e.g., using Intel Integrated Graphics Processors (IGP), we are not required to transfer data. Data could be copied using the CPU or GPU direct memory access (DMA). However, IGPs are generally less powerful than discrete GPUs and thus, not used in our research. To process data in real-time, we have strict requirements for transfer speeds. Since GR has no built-in support for coprocessors, buffers could only be transferred to/from the GPU inside the work() function (where we want our code to be implemented). Every time work() is called by the GR scheduler, we should (i) transfer a portion of input samples (decided by the GR scheduler) from the main memory to the GPU, (ii) perform the PFB channelizer on the GPU and (iii) transfer the channelizer output from the GPU to the main memory. This situation is not optimal as the (i) and (iii) lead to a low throughput and high latency data transmission. For real-time processing, data transfer between CPU and GPU is a time critical action. The time spent transferring data is time lost for processing. It is important to obtain a balance between transfer delay and processing delay. As a solution to this situation, we proposed the following: First, to avoid inefficient data transfer to a single stream, we perform the FDM operation of Fig. 3 inside work(). This is simply done using the stream to streams (s2ss) function, which converts a stream of M items into M streams of 1 item. Hence, we get the inputs of the FIR filters on different streams with different buffers and transfer data more efficiently. Second, to avoid inefficient data transfer (small amount of data with high transferring latency), we batch the s2ss transferring buffers using clEnqueueWriteBuffer() with non-blocking write transfer. With the non-blocking write transfer, control is returned immediately to the host thread, allowing operations to occur concurrently in the host thread during the transfer between host and device proceeds. On the GPU device, as illustrated in Fig. 7, our filter taps are copied to the GPU memory once at the startup of our PFB channelizer. Each GPU FIR filter (inside the PFB channelizer) runs in parallel inside an independent GPU computing unit. Once we get the output from the FIR filters, we pass the output of the FIR filters to the input sequencer such that we can perform the M-point FFT. source library). clFFT usage is straightforward. Here, we take advantage of the functions bakePlan() to apply device optimizations and setPlanBatchSize() to handle several clFFT operations concurrently.

Experimental Results

In this section, we consider the GR CPU-based implementation of the PFB channelizer as a reference. We are using GR version 3.7.5. All experiments are performed on a Linux-based machine with Intel Core i7-4790 @ 3.60 GHz CPU, AMD R9 290 (Tahiti) GPU (4 GB video memory), and 32 GB RAM. We use a simple benchmark experiment illustrated in Fig. 8. The signal source is a GR block used to generate continuously a certain type of a signal, such as sine, cosine or constant. In this experiment, we used gr complex defined in GR as an output to emulate the behavior of a USRP N210. The head block stops the signal source when N items of the gr complex type are processed. Hence, we can configure experiments' duration through N . The s2ss block performs the FDM operation in Fig. 3. We used three implementations for the PFB channelizer: (i) GR with AVX instructions, (ii) our optimized GR implementation with AVX2-FMA instructions, and (iii) our GPU implementation. The channelized streams are sent to a null sink because our target is to evaluate the performance of the PFB channelizer only.

A Running Example

To measure the performance of our solutions proposed in Sections 3-4, we will use a running example based on our passive GSM receiver [START_REF] Alyafawi | Real-time passive capturing of the gsm radio[END_REF]. Each GSM receiver requires a precise sample rate R for each GSM channel: R = 1625000/6 = 270833 complex samples per second (sps), which is equivalent to the data rate of the GSM signal itself. From these numbers, we can calculate a few elements for a wideband GSM receiver:

-We need a wideband sampling rate R b = R * M ch , where M ch is the number of GSM channels. -We can capture up to M ch = 25x10 6 /R = 92 channels using a N210 USRP device with 16 bit precision.

AVX vs AVX2-FMA vs GPU

In these experiments, we want to measure the improvement provided by the optimized AVX2-FMA PFB (presented in Section 3) and the proposed GPU-based PFB (shown in Section 4) compared to the default GR AVX implementation. We use a pre-designed filter of 55 taps, and we want to test the performance for different numbers of channels. The channelizer performance is agnostic to the data content, i.e., feeding a generated signal to the channelizer is the same as feeding a USRP input stream. For each number of channels shown in Fig. 9, we generate a signal equivalent to 60s of data. For example, in experiments with 50 channels, we use a signal source block (a producer of data) with sampling rate R b = 50R and a number of samples X = 60R b . The benchmark output is the total runtime, and the presented results are the arithmetic mean of 5 runs. If the processing time exceeds the 60s, it means that the PFB channelizer cannot process data in real-time. As illustrated in Fig. 9, the improvement using our optimized AVX2-FMA ranges from 30% to 33%. Fig. 10. Taps impact on PFB channelizer.

Taps per Filter

In this experiment, we run the same benchmark as in Section 5.2 with a constant number of channels equal to 25, but varying the number of taps per FIR filter (channel). Again, the results present the arithmetic mean of 5 runs. As illustrated in Fig. 10, the execution time increases with the increasing number of FIR taps. The different zig-zag behavior for AVX and AVX2 implementations is because AVX2 registers have the double size of AVX registers. Extra samples in both implementations are processed using standard non-SIMD operations. This behavior is not noticed in the OpenCL implementation due to the different mechanisms for data transfer from/to GPU. Note that it is important to use a multiple of 2 N so that the compiler can optimize the costly division operation to a bit shifting operation.

Conclusions

GR is the framework of choice for many SDR projects. We demonstrated that it was possible to create high-performance GSM channel processing by reusable components for wideband applications. The channelizer technique is applicable for any distributed system with a set of independent channels. The polyphase filterbank channelizer is not only useful for FDM-based technologies but is a critical component in many SDR systems. Our AVX2 optimizations improve the performance by up to 30 % using recent CPU instructions, namely fused multiply-add operations, compared to the AVX implementation. Moreover, the GPU implementation opens up opportunities for applications, where expensive specialized hardware was required previously. The GPU-based implementation is a GR-like module with 3.2-fold improvement when compared to the original GR implementation on CPU only. Our proposed solutions are available as independent GR modules [START_REF] Channelizer | [END_REF].

Fig. 2 .

 2 Fig. 2. SDR system architecture.

Fig. 5 .

 5 Fig. 5. FMA SIMD operation.

Fig. 6 .

 6 Fig. 6. AVX unpack operation and multiplications.

Fig. 8 .

 8 Fig. 8. PFB channelizer benchmark overview.

Fig. 9 .

 9 Fig. 9. Real time processing of PFB channelizer.

  There are several OpenCL FFT libraries like AMD clFFT (an open

	Read		Write
		GPU memory
	Input buffer	Filter taps	Output buffer
	FIR filterbank	Input Sequencer	FFT
	Fig. 7. PFB Channelizer on GPU.

  Our optimized filter can process in real-time up to 76 channels. It is, however still, lower than what a USRP N210 device can support (c.f., Section 5.1: 92 channels). Compared to the reference channelizer, there is an average of 3.2-fold improvement by the GPU-based PFB implementation. That means we can channelize more than 125 GSM channels, more than what the USRP N210 can capture.

			AVX	AVX2 (FMA)	OpenCL
	better)	20 25	taps mod 16 ≥ mod 8
	is
	(lower time Execution	0 15 10 5	32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 Number of taps per filter