当前位置: 首页 > 知识库问答 >
问题:

按键减少时会导致内存不足

寇坚成
2023-03-14

我正在研究一种需要对大矩阵进行数学运算的算法。基本上,该算法包括以下步骤:

输入:大小为n的两个向量u和v

>

对于两个矩阵中的每个条目,应用一个函数f。返回两个矩阵M_u,M_v

求M_的本征值和本征向量。对于i=0,返回e_i,ev_i,。。。,n-1

计算每个特征向量的外积。返回一个矩阵O_i=e_i*转置(e_i),i=0,。。。,n-1

用e_i=e_i delta_i调整每个特征值,其中delta_i=所有元素之和(O_i和M_v的元素乘积)/2*mu,其中mu是一个参数

最终返回一个矩阵a=i=0,。。。,n-1

我面临的问题主要是当n很大(15000或更多)时的内存,因为这里所有的矩阵都是稠密矩阵。我目前实现这一点的方法可能不是最好的,而且部分有效。

我用行矩阵表示mu,用奇异值分解得到特征分解。

SVD的结果U因子是一个列为ev_i的行矩阵,因此我必须手动转置它,使其行成为ev_i。结果e向量是特征值e_i。

由于内存溢出,之前将每行ev_i直接映射到O_i的尝试失败了

R = U.map{
    case(i,ev_i) => {
      (i, ev_i.toArray.zipWithIndex)
    }
  }//add index for each element in a vector
  .flatMapValues(x=>x)}
  .join(U)//eigen vectors column is appended
  .map{case(eigenVecId, ((vecElement,elementId), eigenVec))=>(elementId, (eigenVecId, vecElement*eigenVec))}

为了在上面的步骤5中计算调整后的e_i,M_v被存储为元组(i,denseVector)的rdd。然后

deltaRdd = R.join(M_v)
  .map{
    case(j,((i,row_j_of_O_i),row_j_of_M_v))=>
    (i,row_j_of_O_i.t*DenseVector(row_j_of_M_v.toArray)/(2*mu))
  }.reduceByKey(_+_)

最后,为了计算A,同样由于内存问题,我必须首先连接来自不同RDD的行,然后按键减少。明确地

R_rearranged = R.map{case(j, (i, row_j_of_O_i))=>(i,(j,row_j_of_O_i))}
termsForA = R_rearranged.join(deltaRdd)
A = termsForA.map{
  case(i,(j,row_j_of_O_i), delta_i)) => (j, (delta_i + e(i))*row_j_of_O_i)
}
.reduceByKey(_+_)

上述实现适用于termsForA的步骤,这意味着如果我对termsForA执行像termsForA. get(1). foreach(println)这样的操作,它就成功了。但是如果我在A上执行操作,比如A. count(),驱动程序上会出现OOM错误。

我试图调整sparks配置以增加驱动程序内存和并行度,但都失败了。

共有2个答案

东方新霁
2023-03-14

我猜Spark在某个时候决定不需要对执行器执行操作,而需要对驱动程序执行所有操作。事实上,termsForA也会像count一样失败。不知何故,我通过广播德尔塔德和e。

郗奇玮
2023-03-14

使用IndexedRowMatrix而不是RowMatrix,这将有助于转换和转置。假设您的IndexedRowMatrix是Irm

svd = Irm.computeSVD(k, True)
U = svd.U
U =  U.toCoordinateMatrix().transpose().toIndexedRowMatrix()

您可以将Irm转换为BlockMatrix,以便与另一个分布式BlockMatrix相乘。

 类似资料:
  • 问题内容: 我正在编写独立于操作系统的无锁队列,到目前为止,它工作得很好,但是内存管理方面的问题很小。我不确定它的gcc问题还是我的。问题:将元素添加到列表时,内存增加,但是从列表中删除元素(free(elementPointer);)时,内存使用率没有变化。 但是,当我使用pthreads时,N个生产者和M个消费者的 内存使用量始终约为10mb(当尝试添加和删除〜10kk元素时),因此看起来自由

  • 我试图使用Spark主机在EC2上使用本指南对常见爬网数据执行简单转换,我的代码如下所示:

  • 问题内容: 我一直在为OpenGL练习编写Minecraft副本(据我估计很多),但是在编写了基本的渲染API之后,我注意到真正的Minecraft 占用了 大量 内存或内存- 大约800MB!我完全可以理解为什么它必须记住所有的块,以及生成器的小怪和地形数据……我问自己:“此块与该块完全相同。它们可以在代码中吗? ” 并记得C ++有指针,所以我试图用我能想到的唯一方法在Java中做同样的事情,

  • 我有一些和等,但是我没有设置。你觉得会是那样吗? 你有什么想法或建议吗? PS:该应用程序在Ubuntu机器上运行 多谢.

  • 问题内容: 我使用io.Copy()复制文件,大约700Mb,但这会导致内存不足 错误信息如下: 我为buf分配了足够的内存,这导致bodyWriter.CreateFormFile()中的内存不足 问题答案: 这是因为您正在“复制”到,这是内存中的缓冲区,从而迫使Go尝试分配与整个文件一样大的内存块。 根据您的使用情况,您似乎正在尝试通过HTTP流式传输文件?在这种情况下,请勿将传递给,而是直接

  • 我使用mockito 1.8.3、jacoco 0.72和maven 3.0.5 surefire插件(2.12.4)来执行单元测试并生成覆盖报告,它运行良好。 随着越来越多的测试被添加,它开始不工作。在测试执行过程中,我不断地遇到内存不足的错误,并且无法找到一种方法来找出问题所在。