Software Archive
Read-only legacy content
17061 Discussions

Baffled & Misaligned (or f90sqlBIND anyone?)

rahzan
Novice
380 Views
If I add the SWQUENCE doirectice to my record I get a warning on misaligned data. Adding the dirctive !DEC$PACK:4 did not make a difference. What can be done about this warning?

FYI:
I am using f90SQL library and a routine fails to get a piece of (bound) data though ODBC if ANY compiler optimization(other than local) is selected.
0 Kudos
8 Replies
Steven_L_Intel1
Employee
380 Views
The warning doesn't affect the operation of your code. SEQUENCE always packs the data unless, and I think this was new in 6.5, you specify /align:sequence.

Whatever problem you're having with f90SQL is not related to the warning.

Steve
0 Kudos
rahzan
Novice
380 Views
Thanks Steve,
I realize the warning does not "affect" the operation but I am concerned about speed degradation resulting from misaligned data(as per user's guide).

How can I make the warning go away?

As per the problem with f90SQL: in geenral what recourse is there when optimization affects the result of the program?

Tim
0 Kudos
Steven_L_Intel1
Employee
380 Views
You can disable alignment warnings globally (Compilation diagnostics - data alignment), or locally with !DEC$ OPTIONS /NOWARN ... !DEC$ ENDOPTIONS around the declarations.

As for figuring out differences - you'd have to see what had changed and why. Do any of these calls "remember" addresses and then write to them after returning from the call?

Steve
0 Kudos
rahzan
Novice
380 Views
Steve,
Thanks for the reply. As for your question I have think about it for a bit.
can;t figure out what "remembering the address" really means!!

I did manage to get the warning to go away by grouping the data in the records from large to small and adding a dummy member which made the total size of the record a multiple of the largest member which was 8. I would have preferred to use %FILL but the decalaration INTEGER %FILL was flatly rejected by the compiler.
What do you make of that??

right now I have a regular unused variable to round out the size.

Tim
0 Kudos
canaimasoft
Beginner
380 Views
Tim,

As I indicated in the answer to the e-mail you sent to us, we cannot further investigate the problem unless you sent the additional information I requested. In any case, please keep in mind that there would be very little benefit in having the compiler optimize data access modules, the processing done behind the scenes (i.e. the driver and the database engine itself), and which out of the control of CVF's optimizer, is what takes most of time/resources.

Regarding Steve's suggestion about the calls, the answer is yes. When you bind a fortran variable to a data set column, what you are effectively doing is telling the driver to use the address of that variable to store the value of a fetched column, when the fetch takes place later in the program. So f90SQLBindCol does "remember" the addresses of the fortran variables you are passing to all the binding procedures.

May be Steve could give us some more insights regarding why and how global optimization might affect this. The interfaces to f90SQL procedures define arguments which addresses will be used later (i.e. "remembered") with no intent or with intent(inout) on the hope that the optimizer would leave them alone...

Marco Garcia
Canaima Software
www.canaimasoft.com
0 Kudos
Steven_L_Intel1
Employee
380 Views
If f90SQL tries to remember the addresses of arguments, it's broken. Which f90SQL routines do this? You should add a VOLATILE declaration for any variables used in this fashion - you can't assume anything about what the compiler might or might not optimize in a program that violates the Fortran standard in this manner.

Steve
0 Kudos
canaimasoft
Beginner
380 Views
Steve,

The VOLATILE declaration must be added by the user to variables they pass to the binding procedures. This is mentioned somewhere in the manual and/or the readme.txt in a topic that specifically explains issues that might arise when compiling with optimization. The same for the use of %loc rather than loc(). I do have to say that we don't use them in the example programs, mainly because they were designed so they would work unmodified in all compilers (CVF,APF,LF95 and FTN95). For the same reason the make files also explicitly don't use optimization.

Regarding the unorthodox method for creating bindings, well that's a very standard technique used in embedded SQL, as well as Windows (e.g. call backs, windproc, etc.). Fortran simply was not designed to do certain things :-). We did not make any assumptions regarding what the compiler does or not, the permanence of deferred buffers (as they are called in ODBC/f90SQL) are the responsibility of the user. Again this is also explained in the manual (including an example of a typical error in which permanence is violated).

There are two f90SQL procedures that use deferred buffers f90SQLBindCol and f90SQLBindParam.

Regards,

Marco Garcia
Canaima Software, Inc.
www.canaimasoft.com
0 Kudos
Steven_L_Intel1
Employee
380 Views
Marco,

Thanks for the explanation. There is no functional difference between %LOC() and LOC() - they're just alternate spellings. We invented %LOC back in 1978, but when LOC() caught on a dozen or so years later, we added that too.

The Fortran language is quite clear that all accesses to variables must be visible to the compiler. A variable is assumed to be accessed when passed as an actual argument, and all COMMON/module variables are assumed to be accessed over a routine call. Other than that, the language allows a compiler to assume that if a variable is not an actual argument and is not in COMMON or a module, then it is not accessed (read or written) during a routine call.

Optimizing compilers can do a lot with this knowledge, including a classic optimization known as "split lifetimes", which allows the compiler to allocate a variable to different locations in different parts of a routine.

If a set of routines such as f90SQL wants to have a "deferred buffer", there is no Fortran-standard-conforming way to do this (other than putting the buffer in COMMON or a module). VOLATILE is a "big hammer" approach which will work - this tells the compiler that it can't assume anything about the variable and must always reference it from the same memory location. A kinder alternative is to pass the address using %LOC or LOC - this clues in the compiler (at least ours) that the address has been "taken", and therefore the variable may be accessed across routine calls.

It is incorrect to simply pass an array, say, as a normal argument, and assume that the address in the argument list can be stored by the called routine for future use. As Tim found, this can lead to bizarre run-time behavior when the compiler decides that the variable now lives somewhere else.

I understand the desire to avoid syntax extensions, but you can't escape them entirely. In my opinion, it would be kinder to define the interface in the context of passed addresses, with loc(), rather than relying on the programmer knowing to add a VOLATILE declaration. (It would certainly be kinder to the compiler support engineers, who end up spending time trying to guess what might be wrong with a program they just have a vague description of.)

By the way, simply compiling without optimization is not a solution - you never know what assumptions the compiler might make.

Steve
0 Kudos
Reply