如何在C ++中存储100000 * 100000矩阵?

时间:2016-02-08 09:53:52

标签: c++

我有两个向量a[100000]b[100000]。我想将a[i]*b[j]存储在矩阵中。我怎么能用C ++做呢?

5 个答案:

答案 0 :(得分:2)

您可以使用std::vector<std::vector<your_type>>存储结果。

int rows = 100000, cols = 100000;

std::vector<std::vector<double>> result;
result.resize(rows);

for(int i=0; i<rows; i++) {
        result[i].resize(cols);
}    

for(int i=0; i<rows; i++) {
    for(int j=0; j<cols; j++){
        result[i][j] = a[i] * b[j];
    }
}

或者你可以使用线性代数库,例如Eigen(你的代码可能会更少),肯定会更高效。< / p>

答案 1 :(得分:2)

  

应该重新研究这个答案的非连续性部分。它   可能是错的。

如果您想使用大量元素,例如100000*100000。由于内部vector of vectors元素的“非连续性”属性,我不建议使用vectors。小push_back可能导致很多混乱。

我会使用带有包装器的单vector。有关详细信息,请参阅此Clean ways to write multiple 'for' loops

答案 2 :(得分:1)

    #include <vector>
    class C
    {
    public:
        C(const std::vector<double>& a_, const std::vector<double>& b_)
            :a(a_),b(b_){};
        double operator()(size_t i, size_t j) const { return a[i]*b[j]; }
    private:
         std::vector<double> a, b;
    };

问题究竟是什么?

原始问题询问了将C(i,j)=A(i)*B(j)保存到矩阵的方法。

从OOP的角度来看,这样的matrix可以定义为一个对象,其中一个方法需要两个输入(ij),并返回一个结果({{ 1}})。

这可以使用嵌套数组预订(ret=A(i)*B(j)),线性数组索引(c[i][j])或函数(c[i*100000+j])来实现。第三种方式也可以简化为仿函数(c.get(i, j)c.operator()(i, j))。

然后是什么?

如果您同意上述所有内容,则三个界面中的任何一个都可达到目的,或至少部分(如我在评论中提到的,如果矩阵仅需要提供随机读取访问权限)它的元素)。然后我们继续实施其中一个,第三个是我的选择。

为什么这样?

我的观察是,计算返回值并不昂贵,所以为什么不计算产品&#34; lazily&#34;什么时候实际访问产品?

通过这种方式,存储非常高效(内存使用量从c(i, j)减少到n^2)。

隐藏getter函数中的乘法不会显着增加访问时间(两次内存访问和一次乘法,与理想情况相比只是一次内存访问,但两种情况都是恒定时间,而且这种实现更加缓存友好减少数据的大小。)

因此,不是保存产品,只需保存输入,但在访问特定元素时计算产品。

缺少什么?

虽然操纵了这个&#34;矩阵&#34;是可能的(通过更改成员2na),它不允许将任意元素更改为任意值。

实现数组切片的成员函数(如b)也不存在,但是可行。

测试代码

c(0:10:end, 4)

<强>演示

http://ideone.com/bZR7AU

答案 3 :(得分:0)

如果系统中的RAM少于80GB(对于100000×100000双打矩阵),则使用in-RAM std::vector<double>可能不可行。

以下是使用mmap'd文件执行此操作的方法。请参阅内联评论:

#include <sys/mman.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define ROWS 1000
#define COLS 1000
#define FILENAME "./matrix.doubles"

int main(void)
{
    double (*matrix)[ROWS][COLS]; // pointer to our matrix
    int fd; // file descriptor of backing file

    // open backing file
    fd = open(FILENAME,
              O_CREAT | O_RDWR, // create (if absent) and/or read and writable
              S_IRUSR | S_IWUSR); // (only) user may read and write
    if (fd < 0) {
        perror("Could not open file");
        return 1;
    }

    if ((lseek(fd, sizeof(*matrix), SEEK_SET) == (off_t) -1) ||
        ftruncate(fd, sizeof(*matrix)) ||
        (lseek(fd, 0, SEEK_SET) == (off_t) -1)) {
        perror("Could not set file size.");
        return 1;
    }

    matrix = mmap(NULL, // I don't care were the address starts
                  sizeof(*matrix), // size of matrix in bytes
                  PROT_READ | PROT_WRITE, // readable and writable
                  MAP_PRIVATE, // we access the data exclusively
                  fd, // file descriptor of backing file
                  0); // offset
    if (matrix == MAP_FAILED) {
        perror("Could not mmap file.");
        return 1;
    }

    // operate on matrix
    for (unsigned row = 0; row < ROWS; ++row) {
        for (unsigned col = 0; col < COLS; ++col) {
            (*matrix)[row][col] = row * col;
        }
    }

    // close backing file
    munmap(matrix, sizeof(*matrix));
    close(fd);

    return 0;
}

这是纯C代码。您可以通过使用例如std::array<double, ROWS, COLS>&而不是裸阵,但我认为这个想法应该是可以理解的。

答案 4 :(得分:0)

如果您可以动态计算[i] * b [j],那么您应该这样做,原因有两个:

  • 从巨大的矩阵中获取结果可能不会比在运行中计算两个双值的乘积更快。
  • 10000x10000双矩阵需要80 GB的存储空间(内存中或磁盘上),并且可能需要一些额外的工作来访问预先计算的数据。

在下面的例子中,如果我在N = 20000的情况下动态计算两个双值的乘积,我会看到加速30倍(使用clang 3.8在发布模式下编译)。

template <typename T>
void test_lookup(std::vector<T> &data, std::vector<size_t> &index,
                 std::vector<T> &results) {
    const size_t LOOP = index.size() / 2;
    for (size_t idx = 0; idx < LOOP; ++idx) {
        auto row = index[2 * idx];
        auto col = index[2 * idx + 1];
        results[idx] = data[col * LOOP + row];
    }
}

template <typename T>
void test_mul(std::vector<T> &x, std::vector<T> &y, std::vector<T> &results) {
    for (size_t idx = 0; idx < x.size(); ++idx) {
        results[idx] = x[idx] * y[idx];
    }
}