Inconsistencies with declaration of 64-bit integers ( signed and unsigned ) in many MKL functions

Inconsistencies with declaration of 64-bit integers ( signed and unsigned ) in many MKL functions

There are inconsistencies with declaration of 64-bit integers ( signed and unsigned ) in many MKL functions. In mkl_types.h there is a declaration:

/* MKL integer types for LP64 and ILP64 */
#if (!defined(__INTEL_COMPILER)) & defined(_MSC_VER)
    #define MKL_INT64 __int64
    #define MKL_UINT64 unsigned __int64
#else
    #define MKL_INT64 long long int
    #define MKL_UINT64 unsigned long long int
#endif

So, MKL_INT64 type is a portable declaration. However, in many MKL functions non-portable declarations long long int and unsigned long long int are used. It creates lots of problems if some legacy C++ compilers are used. For example, Borland C++ v5.x doesn't support  long long int and unsigned long long int types.

 

publicaciones de 36 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.

It is futile to attempt using 64-bit MKL libraries using a 32-bit C compiler. Apart from the 64-bit signed integer problems that you brought up, pointer size, instruction set and ABI are mismatched, and the RTL is unsuitable.

>>...and the RTL is unsuitable...

I'm talking about 64-bit data types and Not 64-bit MKL libraries and everything I needed works (!) already in a 32-bit test environment.

>>...It is futile to attempt using 64-bit MKL libraries using a 32-bit C compiler...

No, I don't use 64-bit MKL DLLs with a 32-bit application built with a 32-bit Borland C++ compiler .

Once again, 32-bit Borland C++ compiler supports __in64 data type ( built-in ) and doesn't support declarations long long int or unsigned long long int.

Also, I've succesfully created a software development environment ( a project for a 32-bit Windows platform / a 32-bit Windows application ) that uses 32-bit MKL with Borland C++ compiler but I was forced to modify some MKL headers because of these inconsistencies with declarations. So, as soon as another developer, who will maintain the codes, will do update for MKL all modified headers will be overwritten and compilation will be broken.

Take into account that in some labs at some universities free legacy C++ compilers are still used.

>>...It is futile to attempt...

I greatly appreciate a really professional / technical feedback and I don't think we need to discuss if this is futile attempt or who needs this, etc.

Sergey,

The first line of the code snippet that you included from mkl.h contained " MKL integer types for LP64 and ILP64 ", and I (incorrectly, it now appears) took it for granted that you were using the LP64 or ILP64 libraries. For the same reason, I did not bother to check whether these lines in mkl.h might remain after preprocessing in 32-bit mode.

MKL does not support Borland C++ compiler. This is the full list of C/C++ compilers supported on Windows. See more information about MKL system requirments here: http://software.intel.com/en-us/articles/intel-mkl-110-system-requirements/

Supported C/C++ and Fortran compilers for Windows*:

  • Intel® Visual Fortran Composer XE 2013 for Windows* OS
  • Intel® Visual Fortran Compiler 13.0 for Windows* OS
  • Intel® Visual Fortran Compiler 13.1 for Windows* OS
  • Intel® C++ Composer XE 2013 for Windows* OS
  • Intel® C++ Compiler 13.0 for Windows* OS
  • Intel® C++ Compiler 13.1 for Windows* OS
  • Microsoft Visual Studio* 2011 - help file and environment integration
  • Microsoft Visual Studio* 2010 - help file and environment integration
  • Microsoft Visual Studio* 2008 - help file and environment integration
  • Microsoft Visual Studio* 2005 Team Suite Edition - help file and environment integration
  • Microsoft Windows* SDK for Windows* 7 (Intel® 64)
  • Microsoft Windows* Software Development Kit Update for Windows Vista* (Intel® 64)
  • Microsoft Windows Server* 2003 R2 Platform SDK (Intel® 64)
  • Microsoft Windows* Software Development Kit for Windows Server* 2008
  • PGI* Workstation Complete version 12.5

Zhang,

A note could be added that any 32-bit versions of MKL could be used with legacy 32-bit Borland C++ compiler(s) and with latest versions of 32-bit MinGW C++ compiler(s). However, some modifications in header files are needed.

What I see that there is still some misunderstanding what I'm talking about and because of this I will provide additional technical details. I detected lots of issues with declarations of MKL functions and they need to be addressed in order to improve portability of MKL. So, my report is almost ready and I will post it soon.

In overall, it took just two working days to integrate MKL and Borland C++ compiler.

Thank you everybody for feedbacks!

[ Note 1 ]

All cases when declarations long long int or unsigned long long int are used need to be replaced with portable, like:
...
#define MKL_INT64 __int64
#define MKL_UINT64 unsigned __int64
...

[ Note 2 ]

mkl_lapacke.h is Not included in mkl_types.h

[ Note 3 ]

Even if in mkl.h there is a define MKL_CALL_CONV:
...
#if defined( MKL_STDCALL )
#define MKL_CALL_CONV __stdcall
#else
#define MKL_CALL_CONV __cdecl
#endif
...
some MKL functions, like cblas_sgemm, are Not declared with any specificator. For example, see in mkl_cblas.h header file:
...
void cblas_sgemm(const CBLAS_ORDER Order, const CBLAS_TRANSPOSE TransA,
const CBLAS_TRANSPOSE TransB, const MKL_INT M, const MKL_INT N,
const MKL_INT K, const float alpha, const float *A,
const MKL_INT lda, const float *B, const MKL_INT ldb,
const float beta, float *C, const MKL_INT ldc);
...

[ Note 4 ]

It would be nice to have a set of macros that control inclusion of all MKL headers files in mkl.h. So, instead of
...
#include "mkl_blas.h"
#include "mkl_dfti.h"
#include "mkl_cblas.h"
#include "mkl_lapack.h"
#include "mkl_solver.h"
#include "mkl_vml.h"
#include "mkl_vsl.h"
#include "mkl_df.h"
#include "mkl_service.h"
...
to have something like ( more controllable way):
...
#ifndef _NO_MKL_BLAS_
#include "mkl_blas.h"
#endif
#ifndef _NO_MKL_DFTI_
#include "mkl_dfti.h"
#endif
#ifndef _NO_MKL_CBLAS_
#include "mkl_cblas.h"
#endif
#ifndef _NO_MKL_LAPACK_
#include "mkl_lapack.h"
#endif
#ifndef _NO_MKL_SOLVER_
#include "mkl_solver.h"
#endif
#ifndef _NO_MKL_VML_
#include "mkl_vml.h"
#endif
#ifndef _NO_MKL_VSL_
#include "mkl_vsl.h"
#endif
#ifndef _NO_MKL_DT_
#include "mkl_df.h"
#endif
#ifndef _NO_MKL_SERVICE_
#include "mkl_service.h"
#endif
...
and it means if a developer doesn't need any functions from mkl_service.h header file it could be controlled as follows:

#define _NO_MKL_SERVICE_
#include "mkl.h"

and so on.

Correction for [ Note 2 ]

mkl_lapacke.h is Not included in mkl.h

My updates affected these MKL header files:

mkl_types.h
mkl_cblas.h
mkl_pardiso.h
mkl_vsl_functions.h

and five Borland linker compatible import libraries created:

mkl_rt.lib
mkl_core.lib
mkl_def.lib
mkl_sequential.lib
mkl_scalapack_core.lib

Here are results of a simple matrix multiplication test with four MKL functions:

Application - BccTestApp - WIN32_BCC - Debug
Tests: Start
> Test1153 Start <

Sub-Test 1.1
Intel(R) Math Kernel Library Version 10.3.12 Product Build 20120831 for 32-bit applications
Major version : 10
Minor version : 3
Update version : 12

Sub-Test 1.2 - Runtime binding of MKL functions
Completed

Sub-Test 3.2 - SGEMM
Matrix multiplication C[ 1024x1024 ] = A[ 1024x1024 ] * B[ 1024x1024 ]
Allocating memory for matrices ( 32-byte alignment )
Intializing matrix data
Measuring performance of SGEMM function
Iteration 01 - Completed in 0.531 secs
Iteration 02 - Completed in 0.500 secs
Iteration 03 - Completed in 0.516 secs
Iteration 04 - Completed in 0.515 secs
Iteration 05 - Completed in 0.516 secs
Deallocating memory

Sub-Test 3.3 - CBLAS_SGEMM
Matrix multiplication C[ 1024x1024 ] = A[ 1024x1024 ] * B[ 1024x1024 ]
Allocating memory for matrices ( 32-byte alignment )
Intializing matrix data
Measuring performance of CBLAS_SGEMM function
Iteration 01 - Completed in 0.515 secs
Iteration 02 - Completed in 0.532 secs
Iteration 03 - Completed in 0.515 secs
Iteration 04 - Completed in 0.516 secs
Iteration 05 - Completed in 0.516 secs
Deallocating memory

Sub-Test 3.4 - DGEMM
Matrix multiplication C[ 1024x1024 ] = A[ 1024x1024 ] * B[ 1024x1024 ]
Allocating memory for matrices ( 64-byte alignment )
Intializing matrix data
Measuring performance of DGEMM function
Iteration 01 - Completed in 0.922 secs
Iteration 02 - Completed in 0.922 secs
Iteration 03 - Completed in 0.922 secs
Iteration 04 - Completed in 0.921 secs
Iteration 05 - Completed in 0.922 secs
Deallocating memory

Sub-Test 3.5 - CBLAS_DGEMM
Matrix multiplication C[ 1024x1024 ] = A[ 1024x1024 ] * B[ 1024x1024 ]
Allocating memory for matrices ( 64-byte alignment )
Intializing matrix data
Measuring performance of CBLAS_DGEMM function
Iteration 01 - Completed in 0.922 secs
Iteration 02 - Completed in 0.969 secs
Iteration 03 - Completed in 0.906 secs
Iteration 04 - Completed in 0.938 secs
Iteration 05 - Completed in 0.890 secs
Deallocating memory

> Test1153 End <
Tests: Completed
Memory Blocks Allocated : 12
Memory Blocks Released : 12
Memory Blocks NOT Released: 0
Memory Tracer Integrity Verified - Memory Leaks NOT Detected

Deallocating Memory Tracer Data Table
Completed

Tests results with different C++ compilers for SGEMM function are very consistent because the same MKL runtime DLLs are used:

[ Intel C++ compiler ]
...
Measuring performance of SGEMM function
Iteration 01 - Completed in 0.532 secs
Iteration 02 - Completed in 0.515 secs
Iteration 03 - Completed in 0.516 secs
Iteration 04 - Completed in 0.516 secs
Iteration 05 - Completed in 0.500 secs
...

[ Borland C++ compiler ]
...
Measuring performance of SGEMM function
Iteration 01 - Completed in 0.516 secs
Iteration 02 - Completed in 0.516 secs
Iteration 03 - Completed in 0.515 secs
Iteration 04 - Completed in 0.516 secs
Iteration 05 - Completed in 0.515 secs
...
[ Microsoft C++ compiler ]
...
Measuring performance of SGEMM function
Iteration 01 - Completed in 0.515 secs
Iteration 02 - Completed in 0.532 secs
Iteration 03 - Completed in 0.531 secs
Iteration 04 - Completed in 0.531 secs
Iteration 05 - Completed in 0.500 secs
...

[ Correction for Note 1 ]

All cases when declarations long long int or unsigned long long int are used need to be replaced with portable MKL_INT64 or MKL_UINT64 based on:
...
#define MKL_INT64 __int64
#define MKL_UINT64 unsigned __int64
...

I am just a casual user of C, but it seems to me that replacing long long int with __int64 would reduce portability. The C99 standard (see for example http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf, section 6.2.5.4) specifies long long int to be a standard integer type. There is no mention of __int64 in the document, and GCC does not recognize it as a native type; perhaps it is a Microsoft C extension that is also supported by Borland C.

Sergey,

Thank you very much for your extensive notes. We will take this into consideration as part of our ongoing effort of making MKL more portable. If you know more about how widely Borland C++ compiler and other legacy compilers are still used in some organizations, please let us know your insight. This will help us to justify our effort.

Thanks again.

http://msinttypes.googlecode.com/svn/trunk/stdint.h

is a visual studio compatible implementation of stdint.h.  I see advantages in such additions to promote portable use of data types.

Thanks for the note about C99 standard.

>>...GCC does not recognize it as a native type; perhaps it is a Microsoft C extension that is also supported
>>by Borland C...

I think initially it could be a joint effort by Intel ( 64-bit instructions set in a CPU \ C++ compiler ) and Microsoft ( support of 64-bit instructions set in OSs \ C++ compiler ). Since Borland was always claiming that compatibility of Borland C++ compiler with Microsoft C++ compiler is very-very high it didn't have a choice and of course it supported these 64-bit types.

Ideally these portable declarations should look like ( in pseudo-codes / more choices as you can see ):

#if ( MSC & ICC )
#define MKL_INT64 __int64
#define MKL_UINT64 unsigned __int64
#endif
#if ( SOME_LEGACY_COMPILER )
#define MKL_INT64 long long int
#define MKL_UINT64 unsigned long long int
#endif
#if ( C99_STANDARD )
#define MKL_INT64 long long int
#define MKL_UINT64 unsigned long long int
#endif
#if ( GCC )
#define MKL_INT64 long long int
#define MKL_UINT64 unsigned long long int
#endif
#if ( BCC & MINGW )
#define MKL_INT64 __int64
#define MKL_UINT64 unsigned __int64
#endif
#if ( MKL_INT64 & MKL_UINT64 Not defined )
#pragma error ( "MKL_INT64 & MKL_UINT64 are Not defined" )
#endif

and the most important:

[ Allowed declaration of MKL function ]

void _CALLING_CONV_ SomeMklFunction( MKL_INT64 arg1, MKL_UINT64 arg2 );

[ Not Allowed declaration of MKL function ]

void _CALLING_CONV_ SomeMklFunction( long long int arg1, unsigned long long int arg2 );

>>...If you know more about how widely Borland C++ compiler and other legacy compilers are still used in some organizations,
>>please let us know your insight...

Unfortunately, I don't have any statistics about usage of legacy C++ compilers. However, take into account that lots of applications were compiled / built with Borland C++ compiler in the past and they still could be used in universities, in small software companies, by independent software developers, etc.

>>...This will help us to justify our effort...

It makes sense to consider and if a positive decision will be made all updates need to be done step by step ( one MKL domain at a time ) because MKL is a very big library.

Thanks, Tim.

>>...is a visual studio compatible implementation of stdint.h. I see advantages in such additions to promote portable
>>use of data types...

I see now where the root cause of the problem is and technical details will be provided after I'll look at some headers from all C++ compilers I use.

Hi,

As I understand the main problem here is in customization of MKL types. Please look at corresponding KB article  http://software.intel.com/en-us/articles/use-of-intel-mkl-data-types-in-cc-applications. Maybe, MKL_UINT64 should allow such customization too as it is done for MKL_INT. However, MKL is common library for C/C++ and FORTRAN. But FORTRAN has no unsigned interger types. Therefore, MKL_UINT and MKL_UINT64 types are kind of C-related compromises in MKL interfaces which look like unnecessary.

Thanks,
-- Victor

Sergey,

My previous post was for your Note1. In my opinion, it’s better to allow/use customization of MKL types instead of collection of all type variants for currently available compilers.

See my comments below on other your Notes2-4.

2) As to mkl_lapacke.h. It is interface for LAPACKE component and it is already part of mkl.h header.

3) As to CDECL/STDCALL calling convention for MKL functions. You know not all functions in MKL can have types of calling conventions. For example some DFTI functions are defined with ellipsis which is not allowed for STDCALL. Maybe some corrections are required to fix MKL interfaces if they need CDECL/STDCALL. We need to check it for CBLAS you mentioned.

4) As to control inclusion of all MKL headers files in mkl.h. I don’t like your suggestion introducing additional macros for including MKL components. In my opinion mkl.h is common MKL header file which includes all MKL components. But if some application needs just several of them it’s better to list them directly instead of mkl.h.

For example to use LAPACKE and SERVICE components:

#include “mkl_types.h”

#include “mkl_lapacke.h”

#include “mkl_service.h”

 

Thanks,
-- Victor

>>...As I understand the main problem here is in customization of MKL types...

No. Declarations of MKL functions should Not use any unwrapped types and see my previous posts.

Here is example:

Currently declared
...
/* SkipAheadStream - skip-ahead method */
#if defined( _MSC_VER )
_Mkl_Api(int,vslSkipAheadStream,(VSLStreamStatePtr , const __int64 ))
_mkl_api(int,vslskipaheadstream,(VSLStreamStatePtr *, const __int64 *))
_MKL_API(int,VSLSKIPAHEADSTREAM,(VSLStreamStatePtr *, const __int64 *))
#else
_Mkl_Api(int,vslSkipAheadStream,(VSLStreamStatePtr , const long long int ))
_mkl_api(int,vslskipaheadstream,(VSLStreamStatePtr *, const long long int *))
_MKL_API(int,VSLSKIPAHEADSTREAM,(VSLStreamStatePtr *, const long long int *))
#endif
...
A modified version 1
...
/* SkipAheadStream - skip-ahead method */
#if defined( _MSC_VER )
_Mkl_Api(int,vslSkipAheadStream,(VSLStreamStatePtr , const __int64 ))
_mkl_api(int,vslskipaheadstream,(VSLStreamStatePtr *, const __int64 *))
_MKL_API(int,VSLSKIPAHEADSTREAM,(VSLStreamStatePtr *, const __int64 *))
#else
_Mkl_Api(int,vslSkipAheadStream,(VSLStreamStatePtr , const MKL_INT64 ))
_mkl_api(int,vslskipaheadstream,(VSLStreamStatePtr *, const MKL_INT64 *))
_MKL_API(int,VSLSKIPAHEADSTREAM,(VSLStreamStatePtr *, const MKL_INT64 *))
#endif
...
Or
A modified version 2
...
/* SkipAheadStream - skip-ahead method */
_Mkl_Api(int,vslSkipAheadStream,(VSLStreamStatePtr , const MKL_INT64 ))
_mkl_api(int,vslskipaheadstream,(VSLStreamStatePtr *, const MKL_INT64 *))
_MKL_API(int,VSLSKIPAHEADSTREAM,(VSLStreamStatePtr *, const MKL_INT64 *))
...
Note: Both versions of modifications Don't change internals of these MKL functions and could be applied very easily ( this is what I was forced to do ).

>>...I don’t like your suggestion introducing additional macros for including MKL components. In my opinion...

I don't think a final decision should be based just on your or my opinions. I regret to see that in some cases developers are trying to "...make an elefant from a fly..." and ready to discuss some subject for weeks if not months when very simple solutions exist.

Sergey,

Firstly, you suggested to change MKL_UINT64 definition to comply with Borland C++. So I said that it's your main problem which can be resolved via customization of MKL_UINT64 type.

As to your comments related to SkipAheadStream definitions, you are right they should use MKL_INT64 type.

Thanks,
-- Victor

Did you read my previous post? I gave a clear example of some problem with declaration of several MKL functions:

Currently declared
...
/* SkipAheadStream - skip-ahead method */
#if defined ( _MSC_VER )
_Mkl_Api( int, vslSkipAheadStream, (VSLStreamStatePtr , const __int64 ) )
_mkl_api( int, vslskipaheadstream, (VSLStreamStatePtr *, const __int64 * ) )
_MKL_API( int, VSLSKIPAHEADSTREAM, (VSLStreamStatePtr *, const __int64 * ) )
#else
_Mkl_Api( int, vslSkipAheadStream, (VSLStreamStatePtr , const long long int ) )
_mkl_api( int, vslskipaheadstream, (VSLStreamStatePtr *, const long long int * ) )
_MKL_API( int, VSLSKIPAHEADSTREAM, (VSLStreamStatePtr *, const long long int * ) )
#endif
...
Once again, these are codes implemented by Intel software developer and they have Non Portable data types long long int and __int64.

Consider it as a bug that could be fixed in less than one minute. Sorry, but we spent more time on writing and reading posts in that thread.

>>...So I said that it's your main problem which can be resolved via customization of MKL_UINT64 type.

Yes, I can do customization and this is actually what I've done by modifying several MKL header files. Now, the main concern / problem is that as soon as another developer ( it is out of my control ) will update MKL all these modifications will be gone. Of course, I could make some instructions but, you know, they could be ignored, or forgotten, etc. Looking ahead I see that as soon as a new update of MKL is installed compilation of sources will be broken if my instructions are not followed by.

Also, I've just completed a verification with MinGW C++ compiler and it perfectly works with long long int-like data types and in overall it took me less than 2 hours to integrate MKL and MinGW.

My conclusion is that MKL could be used with legacy C++ compilers, like Borland ( 32-bit only ), and with GCC-like C++ compiler for Windows, like MinGW ( 32-bit & 64-bit ), but some modifications currently needed in MKL header files. A good thing is that these modifications are very small and don't affect internal implementations of any MKL functions.

So, if my suggestions will be applied some time in the future it will be awesome. Thank you in advance.

Just for consistency with currently used #ifdefs in another header files:

Instead of
...
/* SkipAheadStream - skip-ahead method */
#if defined ( _MSC_VER )
_Mkl_Api( int, vslSkipAheadStream, (VSLStreamStatePtr , const __int64 ) )
...
#else
_Mkl_Api( int, vslSkipAheadStream, (VSLStreamStatePtr , const long long int ) )
...
#endif
...
I think a verification for __INTEL_COMPILER is needed
...
/* SkipAheadStream - skip-ahead method */
#if ( !defined( __INTEL_COMPILER ) ) & defined( _MSC_VER )
_Mkl_Api( int, vslSkipAheadStream, (VSLStreamStatePtr , const __int64 ) )
...
#else
_Mkl_Api( int, vslSkipAheadStream, (VSLStreamStatePtr , const long long int ) )
...
#endif
...

>>>perhaps it is a Microsoft C extension that is also supported by Borland C.>>>

__int64 is Microsoft type specifier.

>>>>...is a visual studio compatible implementation of stdint.h. I see advantages in such additions to promote portable
>>>>use of data types...
>>
>>I see now where the root cause of the problem is and technical details will be provided after I'll look at some headers from
>>all C++ compilers I use.

I still didn't have time to look at it and I hope that I'll do it tomorrow.

Additional verification shows that these four legacy C/C++ compilers do not support declarations long long int and unsigned long long int:

Borland C++ v5.x
Visual C++ 6.x ( also known as Visual Studio 98 )
Turbo C++ v3.x
Turbo C++ v1.x

Even if all tested C/C++ compilers ( released after 2000 ) support these declarations I don't see any reason to support them in MKL because __int64 and unsigned __int64 built-in types exist.

By the way, Intel's intrinsic headers do not have these declarations at all and all 64-bit types are based on __int64 and unsigned __int64 built-in types.

#include "stdio.h"

typedef long int LINT;
typedef long long int LLINT;

LINT liValue = 0;
LLINT lliValue = 0;

int main( void )
{
printf( "sizeof( LINT ) = %d\n", sizeof( LINT ) );
printf( "sizeof( LLINT ) = %d\n", sizeof( LLINT ) );
return ( int )0;
}

Zhang, Victor,

This is simply to let you know that the same modifications with MKL header files are needed in case of using MKL version 11.0.2 with Borland C++ compiler version 5.x. A good thing is MKL functions also perfectly work.

This is a message for David regarding integration of MKL with Borland C++ compilers:

David,

Please do not send me messages using IDZ Messaging System since I'm no longer using it. Sorry about it.

>>This is a message for David regarding integration of MKL with Borland C++ compilers:
>>
>>David,
>>
>>Please do not send me messages using IDZ Messaging System since I'm no longer using it. Sorry about it.

David,

Could you provide some update on a status of your work related to integration of MKL with a version 10 of Borland C++ compiler? Could you also provide more details about the compiler? Thanks.

Deje un comentario

Por favor inicie sesión para agregar un comentario. ¿No es socio? Únase ya