ISO_C_BINDING:对性能/优化的影响

4
在使用MPI的派生数据类型时,我被告知在使用bind(C)结构时要小心,因为它会抑制编译器的某些优化。考虑下面这个(相当不太可能的)例子:
type, bind(C) :: myType
  integer(2) :: a
  complex    :: z
  integer(2) :: b
end type myType

没有使用bind(C)语句,编译器可能会重新排列结构并将两个整数分组以获得更好的对齐。特别是对于大型结构和尝试使用自动向量化时,这将是有益的。
使用bind(C),这种重新分组是不可能的(为了与C兼容,编译器可能不会优化那么多)。如果所有元素都对齐到字,则会导致内存消耗大(三个字而不是两个),或者导致失去对齐。 (至少我被告知是这样的。)
直到最近,我从未混合使用C和Fortran,并且从未在MPI通信中使用派生类型。在不久的将来,我将研究混合语言编程,这些问题似乎很重要。
所以我的问题有两个方面:
  • bind(C):此不对齐是否在“实际应用程序”中发挥作用?有没有人在这里遇到性能/优化问题?
  • iso_c_binding:当(另外)使用模块iso_c_binding时,是否存在其他陷阱?对代码施加了哪些限制并禁用了哪些优化?
1个回答

5

我不会太担心。C编译器在结构体中也会插入填充,特别是元素不是4字节倍数的情况下。更糟糕的是sequence,但那是另一回事。

尝试在C中使用与派生类型等效的代码:

#include <stdio.h>
#include <stdint.h>
#include <complex.h>

typedef struct{
  int16_t  a;
  float complex b;
  int16_t c;
} t;

int main(){
 t o;
 printf("%x %x %x \n",&o.a,&o.b,&o.c);
 return 0;
}

我的编译器(gcc在x86_64上)即使没有进行任何优化,也会将组件对齐到地址的4个字节倍数。更重要的是,当启用所有优化时,gfortran选择的对齐方式恰好与此相同。

iccifortsunccsunf90也使用相同的对齐方式。

  • 模块iso_c_binding本身不应影响优化,因为它仅是一组参数、typedef和过程。但它可能会强制您使用更多指针。

感谢您的解释。所以看来编译器不会优化结构中元素的顺序。我有点惊讶,因为这似乎很容易做到!我将与首先给我建议的人商量一下 - 也许我理解错了什么... - Alexander Vogt
为了达到最大的效率,最好插入填充。它会占用更多的空间,但是访问组件更快,向量化也更容易。 - Vladimir F Героям слава
我是指元素的重新排序... 比如 a,c,b 而不是 a,b,c。这样,结构的大小对于Fortran和C来说都缩小到12个字节,而不是16个字节。仍然需要进行一些填充以实现对齐。 - Alexander Vogt
在 C 中编译器不应该这样做。在 Fortran 中可能是可行的,但对于这种情况并没有太多好处。 - Vladimir F Героям слава
我认为原始顺序是4 + 8 + 4,重新排序后是4 + 4 + 8。 - Vladimir F Героям слава
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接