Fortran-FOSS-Programmers / Best_Practices

the opinionated *best practices* of Fortran FOSS Programmers group
Creative Commons Attribution Share Alike 4.0 International
64 stars 10 forks source link

Be standard? #2

Open szaghi opened 8 years ago

szaghi commented 8 years ago

Dear all,

I start with my first question for you, with the hope you are interested to discuss on.

In my best practices I always considered the standard compliance as a guideline of paramount relevance. However, I know that in some circumstances, extensions could be very helpful. One of my favorite extension (if I can name it as) is OpenMP: even if OpenMP paradigm is not best solution we have, I use it extensively. It is not standard in the sense it is not a part of the Fortran standard (as the brilliant CAF is now!), so I am always in a grey area when I think to OpenMP. However, the OpenMP directives are defined as comments, so my obsessive worries about standardization are partially quieted: even without a compiler supporting OpenMP paradigm, the code could be considered quite standard (at least if there are not specific call OpenMP runtime library I think).

My principal reason to be standard compliance, is portability: I think that if we try to be as standard as possible, portability is greatly enhanced.

What do you think about standardization?

P.S. one reasons why I have not still deeply tried the wonderful Hybrid-Fortran of @muellermichel is related to portability and standardization: codes using Hybrid-Fortran are standard at least in the sense of OpenMP I above described? If I remember right, Hybrid-Fortran enabled codes have specific statement that must parsed by Hybrid-Fortran parser, but @muellermichel can explain. I am citing Hybrid-Fortran beacuse it is just a concrete example where I will happy to lost standard compliance in flavour of great help (in this case parallel performance, great Michel!).

zbeekman commented 8 years ago

I think there should be a hierarchical emphasis on standard compliance:

Just my $0.02

szaghi commented 8 years ago

@zbeekman very clear! This is a very good starting point... hierarchical standard compliance sounds good!

astrojuanlu commented 8 years ago

...and state that sometimes the need of extensions can be solved moving to a more recent standard, e.g. ISO_C_BINDING.

szaghi commented 8 years ago

So, already 3 inputs (with mine)... it seems we can start :tada: @Juanlu001 nice hint!

muellermichel commented 8 years ago

Hey Stefano

Yes, you’re making a good point about standardisation and Hybrid Fortran indeed introduces its own syntax for parallelization. This hasn’t been announced yet, but my plan is actually to add sufficient static analysis to get rid of these non-standard statements and/or convert from standard Fortran to my representation automatically. My mid-term (2017ish) goal is to only have exactly one region that you have to demark: use the accelerator (as a data region) from here to here and do everything needful in between. Setup of domains, including storage order, will be a configuration of this system outside of the actual code.

Now, the point you make about OpenMP and standardization: At least I’m not aware of a general purpose shared-memory parallelization of Fortran code that doesn’t require some trick in the bag like the one used by OpenMP (comments). AFAIK there is basically exactly one possibility of a completely standard compliant way of specifying a parallelization: use procedure pointers and pass them to some parallelization helper that you provide - however you’ll still probably need to implement this somewhere on preprocessor or compiler level, i.e. Fortran is AFAIK not expressive enough to let a library function parallelize something that’s going on inside and do this in a highly performant way for shared memory architectures. I’d be gladly proven wrong on this though.

Best,

Michel

On 11 Jan 2016, at 21:40, Stefano Zaghi notifications@github.com wrote:

Dear all,

I start with my first question for you, with the hope you are interested to discuss on.

In my best practices I always considered the standard compliance as a guideline of paramount relevance. However, I know that in some circumstances, extensions could be very helpful. One of my favorite extension (if I can name it as) is OpenMP: even if OpenMP paradigm is not best solution we have, I use it extensively. It is not standard in the sense it is not a part of the Fortran standard (as the brilliant CAF is now!), so I am always in a grey area when I think to OpenMP. However, the OpenMP directives are defined as comments, so my obsessive worries about standardization are partially quieted: even without a compiler supporting OpenMP paradigm, the code could be considered quite standard (at least if there are not specific call OpenMP runtime library I think).

My principal reason to be standard compliance, is portability: I think that if we try to be as standard as possible, portability is greatly enhanced.

What do you think about standardization?

P.S. one reasons why I have not still deeply tried the wonderful Hybrid-Fortran of @muellermichel https://github.com/muellermichel is related to portability and standardization: codes using Hybrid-Fortran are standard at least in the sense of OpenMP I above described? If I remember right, Hybrid-Fortran enabled codes have specific statement that must parsed by Hybrid-Fortran parser, but @muellermichel https://github.com/muellermichel can explain. I am citing Hybrid-Fortran beacuse it is just a concrete example where I will happy to lost standard compliance in flavour of great help (in this case parallel performance, great Michel!).

— Reply to this email directly or view it on GitHub https://github.com/Fortran-FOSS-Programmers/Best_Practices/issues/2.

szaghi commented 8 years ago

@muellermichel Hi Michel!

my plan is actually to add sufficient static analysis to get rid of these non-standard statements and/or convert from standard Fortran to my representation automatically

Wonderful, it is a great news!

I’m not aware of a general purpose shared-memory parallelization of Fortran code that doesn’t require some trick in the bag like the one used by OpenMP (comments)

Yes, I agree. However, I am thinking that there could be an interesting new option, CAF: I know coarrays are not a shared-memory paradigm, rather a PGAS one, but... how the performances differ from a CAF-code with respect OpenMP-like one on a pure shared-memory architecture? I suspect that performances are similar, so CAF could be an option. However, I have to admit that adding few OpenMP directives cannot be compared to the complexity of refactoring a code to make it CAF-enabled.

Thinking to the Zaak hierarchy, my opinion is that tricks like comments could be admissible as a best-practice, but requiring that the code still works (compiles and runs as expected) if the comments are not parsed (thus, if we need to use, for example, the OpenMP runtime library it could be a serious portability problem on some architectures where we have only a compiler that does not support OpenMP, I am thinking to g95 for example).

AFAIK there is basically exactly one possibility of a completely standard compliant way of specifying a parallelization: use procedure pointers and pass them to some parallelization helper that you provide

Interesting, maybe we can discuss about this in a dedicated thread.

Thank very much Michel for your help!

cmacmackin commented 8 years ago

Another thing which hasn't been mentioned here is the preprocessor. While most projects use it somewhere or other, it is not actually part of any Fortran standard (yes, I know CoCo was, but no compiler supports it and I believe it has since been dropped altogether). A preprocessor is necessary, but even when people use the c-preprocessor it can vary between compilers (gfortran uses a pretty bare-bones standard CPP, while ifort has a somewhat more advanced one referred to as FPP...).

szaghi commented 8 years ago

@cmacmackin You are right! Preprocessor could be an issue into the chain of standardization!

Thank you very much, I was not completely conscious of that.

zbeekman commented 8 years ago

@cmacmackin really good and important point. Dear god, has this been a source of frustration over the years, and AFAICT there is no clear solution or best practice; I'd love to hear everyone else's opinion on this topic... It might even warrant it's own issue/thread.

cmacmackin commented 8 years ago

Another case which strikes me as a potentially acceptable use of non-standard features is one which can be found in my PolyCon project. In that project I make use of gfortran's backtrace subroutine. In this case I use that subroutine to add a bit of extra information in case a certain run-time error is caught and surround the call in precompiler flags so that it would be ignored if being compiled by anything other than gfortran. I guess you could add this (quite low) in the hierarchy as using an extension to provide a non-essential extra feature, protected by precompiler macros in such a way that it should never produce a compiler error.

milancurcic commented 8 years ago

I have learned from the Earth System Modeling Framework (ESMF, https://www.earthsystemcog.org/projects/esmf/) to use __LINE__ and __FILE__ macros for programmatic traceback. Very useful stuff but depends on the preprocessor and thus technically not standard conforming.

szaghi commented 8 years ago

@milancurcic nice, I never read about that.

cmacmackin commented 8 years ago

@milancurcic Wouldn't work in my case, I'm afraid, because the whole point of the traceback is to give the location the client software calls my library from.

milancurcic commented 8 years ago

See simplest example:

$ cat trace.f90 
write(*,*)__LINE__,__FILE__,__DATE__
end
$ ifort -cpp trace.f90 
$ a.out 
           1 trace.f90Jan 11 2016

It becomes very useful once you start returning these as arguments from subroutine calls that encounter an exception.

szaghi commented 8 years ago

@milancurcic wow!

naveen-rn commented 8 years ago

CAF: I know coarrays are not a shared-memory paradigm, rather a PGAS one, but... how the performances differ from a CAF-code with respect OpenMP-like one on a pure shared-memory architecture? I suspect that performances are similar, so CAF could be an option.

Comparing the performance of any CAF implementation with OpenMP is too premature at this stage. CAF is still under its very early stage of standarization & development. In fact, even in future CAF is realistically an alternate for inter-node parallelization models(like MPI, and OpenSHMEM) and not defn for shared memory models(like OpenMP).

milancurcic commented 8 years ago

@cmacmackin Of course! The client application developer is responsible for implementing these calls. It is not clear to me how you cannot get traceback with this method. Implementing this in your library will give you the traceback from deepest levels and going upward. If you enforce the client application to call the library routines with (non-optional) arguments such as line and file, you can obtain full traceback. I did in my application. :)

cmacmackin commented 8 years ago

@milancurcic It could be done and perhaps I'll consider doing so in future. However, the point isn't really to give the traceback from the deepest levels. The point is to let the client know where they called my routine with a bad argument. Since they were clumsy enough to call it with a bad argument in the first place, I'm not sure if they would be bothered to do the error handling correctly. The other issue is that sometimes this error can occur when using the overridden assignment operator. In any case, that whole project was really just a proof of concept on my part and I don't want to derail this whole discussion because of it.

milancurcic commented 8 years ago

@cmacmackin :+1:

LadaF commented 8 years ago

Hi, I think this is a nice initiative.

I have a comment to the __FILE__ and __LINE__ macros. Because there is a line length limit in Fortran these can cause problems. If your code is placed in a directory with a long path, the compilation will crash unless you use a non-standard option to make the limit larger. I especially met this on supercomputers, where the home file system can be mounted to some file-system hierarchy and even the first part of the path can be long. Unfortunately there is no macro just for the filename available.

szaghi commented 8 years ago

@naveen-rn Thank you for your insight.

Yes, I also think that CAF is really young, but I think that has much more potential of MPI & Co. just because it is standard. I already started to play with it (see FOODIE for example), but my experience is very limited ( @zbeekman and @rouson opinions are much more worth than mine). In my simple tests it performs very well on also my shared-memory 12 cores workstation. However, as I said, enabling the code for CAF it is not a matter of inserting few comments. As a perspective, I was thinking that PGAS could be valuable also for shared memory model, do I think wrong? Anyhow, I think it is better to talk about CAF into a dedicated thread if you agree.

Thank you all, I have already learned a lot of things today!

milancurcic commented 8 years ago

@naveen-rn @szaghi My view tends to be that CAF is just a syntax and a really nice one. This is its main advantage in my opinion - the standard defines the syntax and expected behavior, but the compiler developers are responsible for implementing the language features on target hardware. We will eventually be able to generate scalable, standard-conforming code wihout extensions or directives, for many architectures, be it CPUs, MICs or GPU's. Of course, it does and will depend on the underlying machinery and low-level libraries.

@LadaF Excellent points, I agree, these macros must be used with caution!

rouson commented 8 years ago

Wow. This is a fast moving thread and I haven't read every word. I'll just add a couple of disconnected points:

Standards conformance is a high priority for me, but in the short term, it actually hurts portability because of the regrettably uneven compiler support. For my purposes, I've decided to stick to the subset of the standard that matters most for me and is at least supported by gfortran because hypothetically I can install gfortran anywhere. That gives me portability in the sense of being able to move from one platform to another even if it prevents portability in the sense of being able to move from one compiler to another.

To echo sentiments similar to what @milancurcic wrote, CAF enables the expression of parallel algorithms without tying one's implementation to a specific lower-level parallel programming model or hardware architecture. Whether CAF performs well in shared memory or distributed memory or on many-core devices versus GPUs depends heavily on the programming model the CAF compiler developers chose to use. For example, I only recently found out about the MPC thread-based MPI implementation. Such an implementation blurs the distinction between an MPI process and an OpenMP or POSIX thread. They might be one in the same.

On a related note, there is not always a rigid connection between a specific parallel programming model, e.g., CAF, and the way one uses the patterns one uses with that programming model. In this context, I'm using the term patterns in the manner of Mattson et al.. They refer to single program multiple data (SPMD) as a pattern. CAF is of course designed with SPMD in mind and OpenMP is designed with the Fork/Join pattern in mind, but these are not rigid or mutually exclusive approaches.

I've seen some very interesting papers where people did SPMD-style programming using OpenMP by forking all threads at the beginning of execution and only joining them at the end. Likewise, I could imagine someone doing Fork/Join programming with CAF if one master image manages the "forking" (distribution of work and partitioning of data) and the "joining".

There's also a tendency to think of a rigid connection between the parallel programming model and the hardware in the sense of OpenMP being for physically shared memory and MPI being for physically distributed memory, but in particular MPI implementations can exploit shared memory as I believe MPC and others do and there has been at lest one implementation of OpenMP in physically distributed memory: Intel used produce a Cluster OpenMP technology that presented the programmer with a shared memory viewpoint based on handling page faults gracefully to fetch remote data. And there was the SGI Altix line of computers that offered a logically shared-memory view of physically distributed memory. I think that product line survives in some form.

The possible combinations are large and I'd hope we eventually land at a point where CAF has a wide variety of supporting technologies, each of which is chosen to best exploit the particular platform, whether it's shared memory, distributed memory, multi-core, many-core, GPU, or otherwise.

szaghi commented 8 years ago

Ok, it seems that try to have standard compliance is a good advice. I am going to summarize all the above opinions for writing our first guideline... obviously my aim is not fix here the discussion, but just to have other fuel continue it: my English is very bad... please check me!

The very very draft of the very very early summary of the first guideline is coming!

Note: I have no idea of which is the best (clear and concise) format that our document should have. I am just adding it to the readme as it comes into my mind, thus very confused :smiley:

P.S. @rouson thank you very much for your great coments on CAF: I will cut/paste it inyo a dedicated branch with the other related comments posted here.

zbeekman commented 8 years ago

Yes I think we can create markdown documents to hold the content. If needed we can always break the README.md up into other smaller documents but,

flat is better than nested

so I suggest we try to work from just the README.md for now, unless we think of good reasons not to.

szaghi commented 8 years ago

@zbeekman yes, this was my intention: a flat readme. I think we can start with simple approach and see how it evolves.

muellermichel commented 8 years ago

Btw. this sort of stuff is why I'm forced to merge all line continuations as a first step, then preprocess and generate new code, then break up the lines by reintroducing line continuations again, all automatically done before compilation. It's not just these special macros, any macro in Fortran will very easily break your code this way. The fact that Fortran doesn't support multiline macros makes this much worse (I'm using C preprocessor with some special character magic for this reason). IMO Fortran standard macros are pretty much unusable and to be avoided completely. I know this is probably not the place in a discussion a about standardisation, but would it make sense for me to provide my thing as a standalone macro preprocessor for other Fortran projects?

Am 12.01.2016 um 02:00 schrieb LadaF notifications@github.com:

Hi, I think this is a nice initiative.

I have a comment to the FILE and LINE macros. Because there is a line length limit in Fortran these can cause problems. If your code is placed in a directory with a long path, the compilation will crash unless you use a non-standard option to make the limit larger. I especially met this on supercomputers, where the home file system can be mounted to some file-system hierarchy and even the first part of the path can be long. Unfortunately there is no macro just for the filename available.

― Reply to this email directly or view it on GitHub.

SourcerersApprentice commented 8 years ago

Hi All,

Just joined the group, wanted to throw some ideas in.

I agree that if there is a standard way to do something and a nonstandard way, choose the standard way, provided that the implementation details are not too difficult. However, it is the nature of the universe that there will always be a need for a nonstandard approach. My best suggestions for when you absolutely have to go nonstandard is to encapsulate the nonstandard code as much as possible to hide implementation details from the main body of code. In addition, the interface to the encapsulated code should attempt to address the "need" that the nonstandard code supplies, rather than merely satisfying the specific requirements of the implementation.

I will also perhaps be a spotty contributor, but do find several projects here of interest, and hope to help out as I can.

Best regards, Tim Z

rouson commented 8 years ago

I'm not aware of any "macro" capability in Fortran. Could you please explain what is meant by "Fortran standard macros"? Although I wasn't on the committee at he time, my understanding is that macros were discussed years ago in relation to supporting something like C++ templates, but the macro idea was rejected. If there is a new feature to propose, the committee has voted to consider new feature no sooner than 2017, but it's reasonable to develop the idea before then.

I believe conditional compilation is a somewhat analogous capability and it was in the standard at one point. Even though it was removed from the standard, there is at least one open-source conditional compilation tool still in use and under development:

http://www.daniellnagle.com/coco.html

Damian

Sent from my iPhone

Sent from my iPhone

On Jan 11, 2016, at 2:37 PM, Michel Müller notifications@github.com wrote:

Btw. this sort of stuff is why I'm forced to merge all line continuations as a first step, then preprocess and generate new code, then break up the lines by reintroducing line continuations again, all automatically done before compilation. It's not just these special macros, any macro in Fortran will very easily break your code this way. The fact that Fortran doesn't support multiline macros makes this much worse (I'm using C preprocessor with some special character magic for this reason). IMO Fortran standard macros are pretty much unusable and to be avoided completely. I know this is probably not the place in a discussion a about standardisation, but would it make sense for me to provide my thing as a standalone macro preprocessor for other Fortran projects?

Am 12.01.2016 um 02:00 schrieb LadaF notifications@github.com:

Hi, I think this is a nice initiative.

I have a comment to the FILE and LINE macros. Because there is a line length limit in Fortran these can cause problems. If your code is placed in a directory with a long path, the compilation will crash unless you use a non-standard option to make the limit larger. I especially met this on supercomputers, where the home file system can be mounted to some file-system hierarchy and even the first part of the path can be long. Unfortunately there is no macro just for the filename available.

― Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub.

szaghi commented 8 years ago

@SourcerersApprentice thank you very much, your hints is a very good advice (encapsulation). I will add it to this guideline tomorrow.

@rouson I think the above references to Fortran macros are to the widely supported macros like the ones cited by Milan that should be supported by many vendors dven if they are not standard, but maybe I am wrong.

szaghi commented 8 years ago

I have added the draft of our first guideline. Feel free to modify it.

Good night to all.

milancurcic commented 8 years ago

@szaghi is correct, I was (and I believe Michael as well) referring to C preprocessor macros.

muellermichel commented 8 years ago

Hi Damian.

Sorry, I shouldn’t have called it “Fortran standard macros”, you’re correct that such a thing doesn’t exist. IMO there is a sort-of-after-de-fact standard in what gfortran calls “traditional” macros that are enabled when you compile an F90 file (uppercase ending). It’s like a C-preprocessor minus minus, i.e. no stringification and concatenation and no multiline macros. So pretty much only useful for some #ifdefs with simple one-way macro expansions. pgfortran works similarly, Intel seems to be using fpp mostly. And of course fpp also exists in dozens of variations and so far I’m not aware of one thing that works for any compiler and has automatic line splits - I didn’t take the time to examine all the options though, for my tooling I’m trying to not introduce any additional dependencies other than the compiler-of-choice, my repo, and system tools that any developer usually has installed (GNU make and gcc in my case).

Is anyone of you aware of a Fortran preprocessor with above features that plays ball with all common compilers? Preferably something that’s really easy to include in a code repository, such as a single script file. If such a thing exists, would it make sense to document it as part of this Best-Practices effort? As I wrote, if this sort of thing doesn’t exist I could make it pretty easily, i.e. I got all the code already and would only have to assemble it in a standalone manner.

Best, Michel

On 12 Jan 2016, at 07:53, Damian Rouson notifications@github.com wrote:

I'm not aware of any "macro" capability in Fortran. Could you please explain what is meant by "Fortran standard macros"? Although I wasn't on the committee at he time, my understanding is that macros were discussed years ago in relation to supporting something like C++ templates, but the macro idea was rejected. If there is a new feature to propose, the committee has voted to consider new feature no sooner than 2017, but it's reasonable to develop the idea before then.

I believe conditional compilation is a somewhat analogous capability and it was in the standard at one point. Even though it was removed from the standard, there is at least one open-source conditional compilation tool still in use and under development:

http://www.daniellnagle.com/coco.html

Damian

Sent from my iPhone

Sent from my iPhone

On Jan 11, 2016, at 2:37 PM, Michel Müller notifications@github.com wrote:

Btw. this sort of stuff is why I'm forced to merge all line continuations as a first step, then preprocess and generate new code, then break up the lines by reintroducing line continuations again, all automatically done before compilation. It's not just these special macros, any macro in Fortran will very easily break your code this way. The fact that Fortran doesn't support multiline macros makes this much worse (I'm using C preprocessor with some special character magic for this reason). IMO Fortran standard macros are pretty much unusable and to be avoided completely. I know this is probably not the place in a discussion a about standardisation, but would it make sense for me to provide my thing as a standalone macro preprocessor for other Fortran projects?

Am 12.01.2016 um 02:00 schrieb LadaF notifications@github.com:

Hi, I think this is a nice initiative.

I have a comment to the FILE and LINE macros. Because there is a line length limit in Fortran these can cause problems. If your code is placed in a directory with a long path, the compilation will crash unless you use a non-standard option to make the limit larger. I especially met this on supercomputers, where the home file system can be mounted to some file-system hierarchy and even the first part of the path can be long. Unfortunately there is no macro just for the filename available.

― Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/Fortran-FOSS-Programmers/Best_Practices/issues/2#issuecomment-170720689.

francescosalvadore commented 8 years ago

Hi all and thanks for the useful discussion. That made me think on choices I usually do without being aware of. I like the idea of hierarchical compliance. I attempted a wider ranking, even if it does not completely convince myself. The idea is that any programmer should justify the need of using the strategy (n+1) instead of only (1)-(n), and that any code could be characterized by the maximum strategy adopted.

  1. One well-established standard (e.g., Fortran 2003)
  2. Mixing well-established standards keeping one main language (Fortran 2003, OpenMP 3.x, MPI 2, cpp preproc. from C99?)
  3. Mixing well-established standards and different languages (Fortran 2003, OpenMP 3.x, MPI 2, full C99)
  4. Wide spread and portable libraries (BLAS, LAPACK, FFTW, HDF5)
  5. Recent updates of well-established standards (Fortran 2008, OpenMP 4.x, MPI 3)
  6. Well documented and maintained libraries (@szaghi libraries)
  7. "Gentle" extensions: not from vendors, possibly portable and that can be encapsulated (GNU extensions, fpp?)
  8. Library/Extensions (even from vendors) capable of achieving the best goals and performances (CUDA)
  9. Standards, maybe still not well implemented or capable of the best results (OpenACC, OpenCL)
  10. Community libraries not recently updated and/or not well documented
  11. Any other extension (cray-pointers)
  12. Any other piece of code I can find (private libraries, or any file from my hard drive)

Hope it makes sense. Sure it is only my opinion!

szaghi commented 8 years ago

@francescosalvadore wonderful to read you here! :tada: :tada:

By the way, I am updating your post: I think you have done a typo F2013 => F2003.

I agree on your nice hierarchy (except on the citation to my FOSS stuffs...), thank you very much!

muellermichel commented 8 years ago

@francescosalvadore I like the general idea of hierarchical compliance (I think the numbering or n-definition should be the other way round, right?). Where I disagree is in some of the listings. As an example, shouldn't I rely on "wide spread and portable libraries" wherever possible and only implement what doesn't exist yet (for my target architecture)? I'm also not sure about the language mixing being necessarily inferior to pure Fortran solutions. IMO separating a problem into concernes and analysing for each one separately which language is best suited and whether interfacing them costs less than what's gained, can be a superior solution. Especially a Python-Fortran combination is something I think can lead to very clean and performant solutions (Fortran for computational modules that aren't yet covered in NumPy, python for everything else). See game development as an example of Compiled language (C++) + Scripting language (LUA, XML, .. ) duality.

cmacmackin commented 8 years ago

On the issue of lack of a standard preprocessor, we could always try to promote a de-facto standard (at least for use within this group). For example, we could commit to using @szaghi's interesting PreForM. Alternatively, the Generic Preprocessor, for which packages are available on various distributions, looks extremely powerful and versatile. With a wrapper shell script it would be very easy to initialize it to work nicely with Fortran and provide macros for some pretty sophisticated features. Perhaps something we could consider creating another repository for...