Matrix 有没有一种方便的方法可以用数组中的随机值填充稀疏数组?

Matrix 有没有一种方便的方法可以用数组中的随机值填充稀疏数组?,matrix,sparse-matrix,chapel,Matrix,Sparse Matrix,Chapel,我正在比较使用和不使用区域设置的矩阵乘法,并尝试使用稀疏矩阵来处理线性代数模块。我计划使用blockdist,并通过循环手动将其打破,但我想看看现在是否可以通过使用更简单的方法来加速。如果有一种简单的方法可以与我忽略的blockdist合作,我将不胜感激。无论如何,当我用一个值填充稀疏数组时,我能够让代码工作并看到加速,但用随机值填充它似乎不起作用: use LayoutCS; use Time; use LinearAlgebra, Norm; use LinearAlgebra.Sparse

我正在比较使用和不使用区域设置的矩阵乘法,并尝试使用稀疏矩阵来处理线性代数模块。我计划使用blockdist,并通过循环手动将其打破,但我想看看现在是否可以通过使用更简单的方法来加速。如果有一种简单的方法可以与我忽略的blockdist合作,我将不胜感激。无论如何,当我用一个值填充稀疏数组时,我能够让代码工作并看到加速,但用随机值填充它似乎不起作用:

use LayoutCS;
use Time;
use LinearAlgebra, Norm;
use LinearAlgebra.Sparse;
use Random;
use IO;

writeln("Please type the filename with your matrix dimensions. One matrix on each line. The rows in the second need to match the columns in the first");
var filename: string;
filename = stdin.read(string);

// Open an input file with the specified filename in read mode.
var infile = open(filename, iomode.r);
var reader = infile.reader();

// Read the number of rows and columns in the array in from the file.
var r = reader.read(int), c = reader.read(int);

const parentDom = {1..r, 1..c};
var csrDom: sparse subdomain(parentDom) dmapped CS();
var A: [csrDom] real; 
A = 2; //instead of this I would like to do something like fillRandom(A) but it seems to not work

var X: [1..r, 1..c] real; 
fillRandom(X);

//read in the other matrix
var r1 = reader.read(int), c1 = reader.read(int);

const parentDom1 = {1..r1, 1..c1};
var csrDom1: sparse subdomain(parentDom1) dmapped CS();
var B: [csrDom1] real;
B = 3; //same thing as with matrix A

var Y: [1..r1, 1..c1] real; 
fillRandom(Y);

// Close the file.
reader.close();
infile.close();

var t: Timer; //sets up timer
t.start();

var result: [1..r, 1..c1] real; //sets up matrix for results
  
forall i in 1..r do //goes through rows in 1st
  for j in 1..c1 do //goes through 2nd matrix columns
    for k in 1..c do { //goes through columns in 1st
      result[i, j] += X[i, k] * Y[k, j]; //adds the multiplications to the new slot in results
    }

t.stop();
writeln("multiplication took ", t.elapsed()," seconds");
t.clear();


t.start();
var res = A * B;
t.stop();

writeln("loc multiplication took ", t.elapsed()," seconds");
t.clear();
fillRandom对稀疏数组不起作用,还是我做得不对?我是否需要使用循环遍历并手动分配数组中的每个值?当然,我也有可能走错了路,应该多看看blockdist,我肯定会很感激任何关于这方面的建议或提示,因为我不太确定如何确保每个并行任务都在blockdist创建的正确区域设置部分上运行

提前谢谢你

fillRandom对稀疏数组不起作用,还是我做得不对

Random.fillRandom()
在Chapel today(1.22.0)中不支持稀疏数组。然而,我认为这是一个合理的功能请求,如果您有兴趣提交GitHub问题的话

即使
fillRandom
支持稀疏数组,用户仍然需要在用随机值填充那些非零元素之前指定哪些元素是非零的。这是通过向稀疏域添加
(int,int)
元组(或
(int,int)
元组数组)等索引来实现的

以下是生成100x100压缩稀疏行(CSR)阵列的一个小示例,其中包含10个非零随机元素:

/* Example tested with Chapel 1.22 */
import LayoutCS.{CS, isCSType};
import Random;

/* Parent domain dimensions: NxN */
config const N = 100;
/* Number of non-zero elements */
config const nnz = 10;

const parentDom = {1..N, 1..N};
var csrDom: sparse subdomain(parentDom) dmapped CS();
var A: [csrDom] real;

populate(A, csrDom, nnz);

// Print non-zero elements
for (i,j) in csrDom do
  writeln((i,j), ':', A[i, j]);


/* Populate sparse matrix with `nnz` random values */
proc populate(ref A, ref ADom, nnz: int) where isCSType(ADom.dist.type) && isCSType(A.domain.dist.type) {

  // Generate array of random non-zero indices
  var indices: [1..nnz] 2*int;
  var randomIndices = Random.createRandomStream(eltType=int);

  // Replace any duplicate indices with a new random index
  for idx in indices {
    var newIdx = idx;
    while indices.find(newIdx)(1) {
      newIdx = (randomIndices.getNext(ADom.dim(0).low, ADom.dim(0).high),
                randomIndices.getNext(ADom.dim(1).low, ADom.dim(1).high));
    }
    idx = newIdx;
  }

  // Add the non-zero indices to the CSR domain
  ADom += indices;

  // Generate random elements - maybe fillRandom(A) could do this for us some day
  var randomElements = Random.createRandomStream(eltType=A.eltType);
  for idx in ADom {
    A[idx] = randomElements.getNext();
  }
}

关于你更广泛的问题,你能澄清一下你在比较什么吗?阻止分布式CSR矩阵乘法是本地CSR矩阵乘法吗?我要比较的是在一个区域设置上运行矩阵乘法还是在多区域设置系统上运行矩阵乘法。我正在寻找最好的方法来实现这个问题的多语言环境部分,不管是blockdist还是其他什么。我猜如果我真的想按照我说的做,得到一个完整的值矩阵,我必须为矩阵中的每个索引添加非零索引?这似乎是对稀疏数组的浪费,所以我很确定这不是我应该使用的,除非我遗漏了其他东西。谢谢你的帮助!是的,如果您打算使稀疏数组的每个元素都非零,那么使用稀疏数组的任何好处都将丢失。你能使用一个默认的矩形数组吗?或者使用稀疏还有其他动机吗?我使用稀疏是因为它似乎是唯一一个与线性代数模块一起工作的数组,尽管我可能误解了这一点。我可能会继续使用blockdist,因为使用lin-alg似乎无法利用区域设置。
linearlgebra
模块支持默认矩形数组,而
linearlgebra.Sparse
子模块支持CSR(Sparse)数组。BlockDist支持是一项正在进行的工作,但是它应该在1.22中与矩阵乘法一起工作(现在在主分支上得到了改进)。