2

我对 C++ 比较陌生,仍然对如何将数组作为参数传递和返回感到困惑。我想写一个简单的矩阵向量积c = A * b函数,签名像

times(A, b, c, m, n)

其中A是二维数组,b是输入数组,c是结果数组,mn是 的维度A。我想通过mand指定数组维度n,而不是通过A.

(并行)函数的主体是

int i, j;
double sum;

#pragma omp parallel for default(none) private(i, j, sum) shared(m, n, A, b, c)
for (i = 0; i < m; ++i) {
    sum = 0.0;
    for (j = 0; j < n; j++) {
        sum += A[i][j] * b[j];
    }
    c[i] = sum;
}
  1. 像这样的函数的正确签名是什么?
  2. 现在假设我想在函数中创建结果数组 c 并返回它。我怎样才能做到这一点?
4

3 回答 3

2

这是你应该使用的答案......所以解决这个问题的一个好方法是创建一个structclass包装你的数组(好吧,数据缓冲区 - 我会使用 a std::vector)。而不是像这样的签名times(A, b, c, m, n),而是使用这种语法:

Matrix<4,4> M;
ColumnMatrix<4> V;
ColumnMatrix<4> C = M*V;

其中 M 的宽度/高度在<4,4>数字中。

Matrix 类的速写可能是(有点不完整——例如,没有 const 访问)

template<size_t rows, size_t columns>
class Matrix
{
private:
  std::vector<double> values;
public:
  struct ColumnSlice
  {
    Matrix<rows,columns>* matrix;
    size_t row_number;
    double& operator[](size_t column) const
    {
      size_t index = row_number * columns + column;
      Assert(matrix && index < matrix->values.size());
      return matrix->values[index];
    }
    ColumnSlice( Matrix<rows,columns>* matrix_, size_t row_number_ ):
      matrix(matrix_), row_number(row_number_)
    {}
  };
  ColumnSlice operator[](size_t row)
  {
    Assert(row < rows); // note: zero based indexes
    return ColumnSlice(this, row);
  }
  Matrix() {values.resize(rows*columns);}
  template<size_t other_columns>
  Matrix<rows, other_columns> operator*( Matrix<columns, other_columns> const& other ) const
  {
    Matrix<rows, other_columns> retval;
    // TODO: matrix multiplication code goes here
    return std::move(retval);
  }
};

template<size_t rows>
using ColumnMatrix = Matrix< rows, 1 >;

template<size_t columns>
using RowMatrix = Matrix< 1, columns >;

以上使用了您的编译器可能没有的 C++0x 功能,并且可以在没有这些功能的情况下完成。

这一切的意义何在?您可以拥有看起来像数学并且在 C++ 中做正确事情的数学,同时非常高效,就是“正确”的 C++ 方法。

std::vector如果您更习惯使用C++ 的某些功能(例如处理数组内存管理),还可以使用类似 C 的方式进行编程。但这是对这个问题的不同答案。:)

(注意:上面的代码尚未编译,也不是完整的 Matrix 实现。但是,您可以在野外找到基于模板的 Matrix 实现。)

于 2012-11-02T15:30:41.090 回答
2

所以不是“你应该宁愿”回答(我会留下,因为你真的应该宁愿!),这里是“你要求的”答案。

我会std::vector用来保存您的数组数据(因为它们具有 O(1) 移动功能)而不是 a std::array(这可以为您节省间接费用,但移动成本更高)。 std::vectormalloc'd(和realloc'd)缓冲区std::array的C++“改进”,而是char foo[27];样式缓冲区的C++“改进”。

std::vector<double> times(std::vector<double> const& A, std::vector<double> const& b, size_t m, size_t n)
{
  std::vector<double> c;
  Assert(A.size() = m*n);
  c.resize(n);

  // .. your code goes in here.
  // Instead of A[x][y], do A[x*n+y] or A[y*m+x] depending on if you want column or
  // row-major order in memory.
  return std::move(c); // O(1) copy of the std::vector out of this function
}

您会注意到我稍微更改了签名,以便它返回 std::vector 而不是将其作为参数。我这样做是因为我可以,而且它看起来更漂亮!

如果您确实必须传入c函数,请将其作为 a 传入std::vector<double>&- 对 a 的引用std::vector

于 2012-11-02T15:52:41.267 回答
0

法向量矩阵乘法如下:

friend Vector operator*(const Vector &v, const Matrix &m);

但是如果要单独传递维度,则如下:

friend Vector mul(const Vector &v, const Matrix &m, int size_x, int size_y);

由于 Vector 和 Matrix 将是 1d 和 2d 数组,它们看起来像这样:

struct Vector { float *array; };
struct Matrix { float *matrix; };
于 2012-11-02T15:52:13.043 回答