高性能计算中更好的做法是什么:将数据结构传递给函数或一组变量?
What is better practise in high-performance computing: passing a struct of data into a function or a set of variables?
假设我有一个结构,其中包含一组描述对象的变量,在我的例子中是一个网格。我想知道,如果我有一个只使用网格子集的函数,下面 computational_kernel
函数的两个变体是否有任何性能差异。内核是相同的,除了传递结构的内核必须在完成大量计算之前从结构中提取 itot
、jtot
和 ktot
。
struct Grid
{
int itot;
int jtot;
int ktot;
int not_used_in_kernel1;
int not_used_in_kernel2;
int not_used_in_kernel3;
int not_used_in_kernel4;
}
Grid grid;
// Code that initializes the grid values...
// Variant 1
computational_kernel(double* array1, double* array2,
const int itot, const int jtot, const int ktot);
// Variant 2
computational_kernel(double* array1, double* array2,
const Grid& grid);
我认为传递结构对代码维护更好。如果您向网格中添加新字段,则只需更改函数即可。但是传递一组变量你将不得不改变函数和对函数的每次调用。
我想说的是,像第二个变体那样传递对结构的引用在性能方面可能更高效。在第一个变体中,调用者需要将 3 个 int 变量压入堆栈,而在第二个变体中,它所需要压入的只是对结构的引用(指针)并在那里执行操作。如果要传递的变量超过 3 个,性能影响当然会更大。
如果 computational_kernel
是一个在内部做很多工作并且被调用几次的函数,那么两个版本之间的差异是无穷小的。第二个版本只是取消引用 3 个值的额外成本,其余的是相同的,并且您可能必须在调用第一个版本之前无论如何都要进行这种取消引用。
出于紧凑的原因,我肯定会使用第二种形式:如果您正在定义面向对象的数据结构,那么以这种方式使用它们(更好的封装)。
假设我有一个结构,其中包含一组描述对象的变量,在我的例子中是一个网格。我想知道,如果我有一个只使用网格子集的函数,下面 computational_kernel
函数的两个变体是否有任何性能差异。内核是相同的,除了传递结构的内核必须在完成大量计算之前从结构中提取 itot
、jtot
和 ktot
。
struct Grid
{
int itot;
int jtot;
int ktot;
int not_used_in_kernel1;
int not_used_in_kernel2;
int not_used_in_kernel3;
int not_used_in_kernel4;
}
Grid grid;
// Code that initializes the grid values...
// Variant 1
computational_kernel(double* array1, double* array2,
const int itot, const int jtot, const int ktot);
// Variant 2
computational_kernel(double* array1, double* array2,
const Grid& grid);
我认为传递结构对代码维护更好。如果您向网格中添加新字段,则只需更改函数即可。但是传递一组变量你将不得不改变函数和对函数的每次调用。
我想说的是,像第二个变体那样传递对结构的引用在性能方面可能更高效。在第一个变体中,调用者需要将 3 个 int 变量压入堆栈,而在第二个变体中,它所需要压入的只是对结构的引用(指针)并在那里执行操作。如果要传递的变量超过 3 个,性能影响当然会更大。
如果 computational_kernel
是一个在内部做很多工作并且被调用几次的函数,那么两个版本之间的差异是无穷小的。第二个版本只是取消引用 3 个值的额外成本,其余的是相同的,并且您可能必须在调用第一个版本之前无论如何都要进行这种取消引用。
出于紧凑的原因,我肯定会使用第二种形式:如果您正在定义面向对象的数据结构,那么以这种方式使用它们(更好的封装)。