我有两个向量a[100000]
和b[100000]
。我想将a[i]*b[j]
存储在矩阵中。我怎么能用C ++做呢?
答案 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
可以定义为一个对象,其中一个方法需要两个输入(i
和j
),并返回一个结果({{ 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;是可能的(通过更改成员2n
和a
),它不允许将任意元素更改为任意值。
实现数组切片的成员函数(如b
)也不存在,但是可行。
测试代码
c(0:10:end, 4)
<强>演示强>
答案 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],那么您应该这样做,原因有两个:
在下面的例子中,如果我在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];
}
}