- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi all,
Recently I'm trying to call qsort to sort a long integer array on Linux, however, the result looks like wrong. And I try to call qsort to sort the same array on Windows, finding that the result is correct. Is there something wrong when I call qsort on Linux? Any suggestions will be appreciated!
The codes call qsort on Linux are as follows:
Module Share_Type_GPU
Type Element_Type_GPU
Integer :: Row
Integer :: Col
Integer(8) :: Index
Double Precision :: Val
End Type
End Module Share_Type_GPU
Subroutine Qsort_COO_Linux_GPU
Use Global_Variables, ONLY: Nelem,Nevab,Mposn
Use,Intrinsic :: Iso_C_Binding, ONLY: C_Size_T
Use Ifport, ONLY: Qsort_Element_Types_GPU => Qsort
Use Share_Type_GPU
Interface
Subroutine Qsort(Array, Len, Isize, Comp)
Use, Intrinsic :: Iso_C_Binding, Only: C_Size_T
Use Share_Type_GPU
Type(Element_Type_GPU) Array(Len)
Integer(C_Size_T) Len, Isize
Integer(8), External :: Comp
End Subroutine Qsort
End Interface
Type(Element_Type_GPU) :: C(Nelem*Nevab*Nevab)
Integer(8), External :: Cmp_Function_GPU
Integer (C_Size_T) :: Size_Of_Element, Size_Of_Array
Integer I
Do I=1,Nelem*Nevab*Nevab
C(I)%Val = COO_Value(I)
C(I)%Row = COO_Index(I,1)
C(I)%Col = COO_Index(I,2)
C(I)%Index = COO_Index(I,2)*Mposn+COO_Index(I,1) ! Long integer larger than integer(4), so use integer(8)
End Do
Size_Of_Array = Size(C)
Size_Of_Element = Sizeof(C(1))
Call Qsort(C, Size_Of_Array, Size_Of_Element, Cmp_Function_GPU)
Do I=1,Nelem*Nevab*Nevab
COO_Value(I) = C(I)%Val
COO_Index(I,1)= C(I)%Row
COO_Index(I,2)= C(I)%Col
End Do
Return
End Subroutine
Function Cmp_Function_GPU(C1, C2)
Use Share_Type_GPU
Implicit None
Type(Element_Type_GPU), Intent(In) :: C1
Type(Element_Type_GPU), Intent(In) :: C2
Integer(8) :: Cmp_Function_GPU
Cmp_Function_GPU=C1%Index-C2%Index
End Function
Thank you very much!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We don't have a full compilable example here, but I suggest going back to the documentation for the ifport implementation of qsort and comparing what you have done with the example there. One obvious thing that stands out to me is that you have declared the compare function to have a return value of integer(8), when the documentation suggests integer(2).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Might be onto something with the integer(2) vs. integer(8)
If the comp argument is passed by reference, the endianness of windows provide a little leeway to get it wrong.
If I pass an integer(8) value to a routine expecting integer(2) on windows, it will work as expected because the first two bytes
of an integer(8) value that would fit into an integer(2) are the same as the integer(2)
For example integer(8) value of 1 on windows shows up in memory as 01 00 00 00 00 00 00 00
and integer(2) value of 1 shows up in memory as 01 00. So if I pass the address of integer(8) 1 to a routine expecting integer(2), it
still works.
On unix systems the order in memory is swapped to something a bit for user friendly, such that integer(8) value of 1 is
00 00 00 00 00 00 00 01
and integer(2) value of 1 is
00 01
But then passing integer(8) by reference to a routine expecting integer(2), the subroutine will see the first 2 bytes of the integer(8) number, and so it would see 0 instead of 1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi cryptogram,
Your suggestion successfully solves my problem. It finally works!
Thanks for your help!
-Yu
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Mark,
Your suggestion successfully solves my problem. It finally works!
Thanks for your help!
-Yu
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page