specs-feup / specs-lara

MIT License
0 stars 0 forks source link

Code outside the scope for Polybench is edited by AutoPar #1

Open aubertc opened 2 years ago

aubertc commented 2 years ago

If I compare e.g. the original file of the 3mm.c test of the PolyBench suite with the expected output, then there are some changes outside of the kernel_3mm function.

For instance, the header:

https://github.com/specs-feup/specs-lara/blob/06b1422430e13b6b55c1f864bb0dfd9fa2293f20/ANTAREX/AutoPar/Polybench/3mm/3mm.c#L26-L30

has some variables replaced by their values:

https://github.com/specs-feup/specs-lara/blob/06b1422430e13b6b55c1f864bb0dfd9fa2293f20/ANTAREX/AutoPar/Polybench/3mm/expected_output.c#L20

My understanding was that any edit to the polybench source files should happen inside that function definition, and not outside.

Is this unavoidable? Is there, at least, a workaround to not delete the timer instructions (at https://github.com/specs-feup/specs-lara/blob/06b1422430e13b6b55c1f864bb0dfd9fa2293f20/ANTAREX/AutoPar/Polybench/3mm/3mm.c#L159-L161 , that are simply removed in https://github.com/specs-feup/specs-lara/blob/06b1422430e13b6b55c1f864bb0dfd9fa2293f20/ANTAREX/AutoPar/Polybench/3mm/expected_output.c#L122-L124 )?

joaobispo commented 2 years ago

The code that is being replaced are macros. You could say this is a limitation of the C/C++ language, that perform those transformations during the pre-processor phase, and that when the code is parsed, those changes already happened.

Clava parses the code (with the help of Clang) into an Abstract-Syntax Tree (AST), and then regenerates the code from the AST. We try to revert some of the changes introduced by the pre-processor (e.g. re-insert #include directives, comments), but not generally.

Usually this is not a problem, since we tend to use Clava to apply a set of transformations before the compiler (as it happens with the CMake package), so we are not worried about the macros being resolved, the generated code is "temporary". I suspect the timer instructions are being deleted because they are controlled by #define directives that are not being set (you can use the flag -fs to pass any set of C/C++ compiler flags that you would pass to Clang/gcc).

However, there is a possible solution, that requires some work, which is to recreate the source files directly, in a textual manner. The function Parallelize.getForLoopPragmas can be used to calculate the OpenMP pragmas, without changing the code. You will receive an object that maps loop ids to the corresponding OpenMP pragma, and with the $loop node, you can also access the corresponding $file (using $loop.ancestor('file')), which contains the path to the original file. You can also access the line where the loop appears ($loop.line), so you have all the information for textually recreating the source file, inserting the pragmas before the lines of the loops.

Tip: this is fairly easy to do if you read the source file as a list of strings, one per line, and insert the corresponding pragmas in reverse order, as new elements of the list.

aubertc commented 2 years ago

Thanks a lot, that is very useful.

We try to revert some of the changes introduced by the pre-processor (e.g. re-insert #include directives, comments), but not generally.

Ok, that's what threw me off: I thought all the original source code was restored, hence my confusion.

However, there is a possible solution, that requires some work,

Thanks a lot for drafting it, I think for the time being I will "simply" copy-and-paste the pragma directive back into the original source code.

But then I have another question, somewhat related (I can open a different issue if you prefer) about the fdtd-2d.c file from the Polybench/C suite.

joaobispo commented 2 years ago

Ok, that's what threw me off: I thought all the original source code was restored, hence my confusion.

This is more of an issue of C/C++ regarding the preprocessor and code generation from AST (if you want to check the "real" C/C++ code that goes to the parser after the text-substitution of the preprocessor is done, try compiling the code with the flag -E, e.g., gcc -E foo.c). We have equivalent tools for other languages (e.g. Java, JavaScript) where it is much easier to obtain code very close to the original (without regards for the original formatting).

about the fdtd-2d.c file from the Polybench/C suite. Why is not included in https://github.com/specs-feup/specs-lara/tree/master/ANTAREX/AutoPar/Polybench ?

I had not noticed this. It is indeed strange, since we even have results for fdtd-2d in the AutoPar papers. I will have to check this, and consider updating the dataset.

why is it "hard-coding" the values for LARGE_DATASET?

I think this is happening because LARGE_DATASET is the default dataset in Polybench, for instance in the file fdtd-2d.h there is this code:

/* Default to LARGE_DATASET. */
# if !defined(MINI_DATASET) && !defined(SMALL_DATASET) && !defined(MEDIUM_DATASET) && !defined(LARGE_DATASET) && !defined(EXTRALARGE_DATASET)
#  define LARGE_DATASET
# endif

If you do not set a specific dataset (e.g. flag -DSMALL_DATASET for the small dataset), LARGE_DATASET is used. For the Clava use case I've mentioned, where it applies transformations just before the compiler, this usually is not a problem, since the pragmas are generated just before compilation, and you can control the dataset size in the Polybench benchmark using compilation flags.

If you want to manually extract the pragmas and insert them in the source code, you should also manually replace the hardcoded values with the corresponding macros (e.g. NX, NY).