You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Reusability of preprocessing functions to reduce code bloat #297
If we have a stream A in a copilot specification that is defined by applying some preprocessing to another stream B (say an external signal), it seems that in the generated code the calculation of stream A would implement the whole preprocessing to calculate it from stream B. But this means that if there is some involved preprocessing function that is commonly used in the specification (i. e. some filtering function or a function to define state transitions in a large state machine) then the preprocessing code would be reimplemented again many times which could lead to bloated .text section in generated binary.
If there is a commonly used preprocessing function it would be good to have it defined once and to be reused in the constructions of the streams in generated C code. Is there some way to do that?
Activity
antanas-kalkauskas-sensmetry commented on Feb 28, 2022
A quick example to illustrate the issue. Say we have three signals to which we apply the same preprocessing function:
{-# LANGUAGE RebindableSyntax #-}
modulePreprocessingReimplementedwhereimportLanguage.CopilotimportCopilot.Compile.C99signal1::StreamFloat
signal1 = extern "signal1"Nothingsignal2::StreamFloat
signal2 = extern "signal2"Nothingsignal3::StreamFloat
signal3 = extern "signal3"Nothing-- some example filter constants
a =1
b =2
c =3-- just an example of preprocessing, this can be much more complicatedinvolvedPreprocessing::StreamFloat->StreamFloat
involvedPreprocessing x = y
where y = a*x + b*([0]++y) + c*([0, 0]++y)
spec =do
trigger "triggerFunction1" (involvedPreprocessing signal1 >10) [arg (involvedPreprocessing signal1)]
trigger "triggerFunction2" (involvedPreprocessing signal2 >10) [arg (involvedPreprocessing signal2)]
trigger "triggerFunction3" (involvedPreprocessing signal3 >10) [arg (involvedPreprocessing signal3)]
main::IO()
main =do
reify spec >>= compile "preprocessing_reimplemented"
If we look in the generated C code we would see that the filter functions are repeatedly implemented 3 times:
At present, there is no way to define these kinds of re-usable functions in Copilot. It is a good idea to have them, but it's not in our immediate plans because we are working on other features.
The only way possible as far as I can think is to rely on existing optimizers for C code that could factorize that out.
That being said: is the size of the .text sections being generated a serious issue? (I see how it could potentially be, but is there a real-world problem that needed solving and you could not use copilot for for this reason?)
We are evaluating using Copilot in a scenario where there is significant function reuse for many input signals. In our initial explorations, the increase of ROM relative to a reasonable handwritten code would be a factor of 10 (if not more) and this makes it infeasible to use Copilot code in an embedded system.
I have an idea of how we could do this. We need to introduce a construct for named functions of all arities, a way to define named functions and add them to the spec, and a way to compose and combine OP{1,2,3} with each other.
Activity
antanas-kalkauskas-sensmetry commentedon Feb 28, 2022
Example
A quick example to illustrate the issue. Say we have three signals to which we apply the same preprocessing function:
{-# LANGUAGE RebindableSyntax #-} module PreprocessingReimplemented where import Language.Copilot import Copilot.Compile.C99 signal1 :: Stream Float signal1 = extern "signal1" Nothing signal2 :: Stream Float signal2 = extern "signal2" Nothing signal3 :: Stream Float signal3 = extern "signal3" Nothing -- some example filter constants a = 1 b = 2 c = 3 -- just an example of preprocessing, this can be much more complicated involvedPreprocessing :: Stream Float -> Stream Float involvedPreprocessing x = y where y = a*x + b*([0]++y) + c*([0, 0]++y) spec = do trigger "triggerFunction1" (involvedPreprocessing signal1 > 10) [arg (involvedPreprocessing signal1)] trigger "triggerFunction2" (involvedPreprocessing signal2 > 10) [arg (involvedPreprocessing signal2)] trigger "triggerFunction3" (involvedPreprocessing signal3 > 10) [arg (involvedPreprocessing signal3)] main :: IO () main = do reify spec >>= compile "preprocessing_reimplemented"If we look in the generated C code we would see that the filter functions are repeatedly implemented 3 times:
In this case the code bloat is not significant, but this is just an example to illustrate the issue.
ivanperez-keera commentedon Feb 28, 2022
At present, there is no way to define these kinds of re-usable functions in Copilot. It is a good idea to have them, but it's not in our immediate plans because we are working on other features.
The only way possible as far as I can think is to rely on existing optimizers for C code that could factorize that out.
That being said: is the size of the .text sections being generated a serious issue? (I see how it could potentially be, but is there a real-world problem that needed solving and you could not use copilot for for this reason?)
antanas-kalkauskas-sensmetry commentedon Feb 28, 2022
We are evaluating using Copilot in a scenario where there is significant function reuse for many input signals. In our initial explorations, the increase of ROM relative to a reasonable handwritten code would be a factor of 10 (if not more) and this makes it infeasible to use Copilot code in an embedded system.
ivanperez-keera commentedon Jan 25, 2025
I have an idea of how we could do this. We need to introduce a construct for named functions of all arities, a way to define named functions and add them to the spec, and a way to compose and combine
OP{1,2,3}with each other.ivanperez-keera commentedon Jan 25, 2025
And I suspect that, if we do that, we might be able to get rid of or re-define the interface of
local, and thus be able to close issue #253.