【问题标题】:C++ Job Interview Question Made Harder, how to solve?C++ 求职面试问题变得更难了,如何解决?
【发布时间】:2021-09-15 19:20:40
【问题描述】:

我最近参加了一次工作面试,要求我将 2 个矩阵相乘,这真的很容易。然后有人问我:

想象一下,当读取任何矩阵的一个值时,CPU 会从右边得到 4 个相邻的值,你如何利用这个事实来提高性能?

起初我虽然将每 4 个值保存在变量中,而不是读取 A[i][j],我可以简单地检查变量,但这根本没有帮助,因为我们仍然从内存中读取值,因此没有单一优势...

【问题讨论】:

  • 听起来他们在要求您使用 SIMD,但这并不完整:您需要 4 宽度的算术运算才能充分利用 4 宽度的负载。有没有关于那件事的说法?
  • @harold 我想他不是这个意思,这是实习面试
  • 矩阵乘法通常涉及向下一个的行和另一个的列。如果您首先转置其中一个矩阵,则可以通过向下每个矩阵的行(或列)进行乘法运算,以便内存提前获取帮助。虽然转置创建了一个新矩阵,但它是一个 O(1) 操作,并且对于更大的矩阵,增益将抵消它。
  • 为什么会提到What's the use of do while(0) when we define a macro? [duplicate] 问题?它们是无关的。
  • 我不知道重复项与问题有什么关系......实际的问题是,“当读取任何矩阵的一个值时,CPU 会给你 4 个相邻的右边的”意味着它只得到四个相邻的而不是你要求的那个?或者这是否意味着您获得了 5 个值:您读取的一个值和另外四个值?因为那会改变答案。

标签: c++ c memory


【解决方案1】:

优化矩阵乘法没有单一的方法,这里有一种方法。我不知道你的面试官期望的是相似的还是完全不同的。

该方法确实需要您以特殊方式存储矩阵(既不是行优先也不是列优先),但所有矩阵的存储方式始终相同,因此无需在行优先和列优先表示之间切换(中间结果没有转置)。

基本思想是将矩阵存储为 2x2 元素块的二维数组。换句话说,你可以这样安排

a[2*i+0][2*j+0]
a[2*i+0][2*j+1]
a[2*i+1][2*j+0]
a[2*i+1][2*j+1]

在内存中是连续的,因此它们被一起提取和存储。

然后您只需将矩阵逐块相乘(一行块乘以一列块)。

您将需要填充奇数大小的矩阵,但对于大矩阵,这并不是非常昂贵。

【讨论】:

  • 你仍然没有使用我们正在读取内存块的事实......你确实 left[i][k] 所以让我们假设 k 是 0 然后你访问 left[i][0 ] 然后你再次访问你已经拥有的 left[i][1] 。您没有在问题中使用额外奖励。
  • 这个答案不是来自我的头脑,而是来自我碰巧熟悉的真实硬件和软件。恐怕我无法更好地解释它,所以我将这个答案留给未来的读者。
猜你喜欢
  • 2021-07-31
  • 2022-01-26
  • 2010-12-16
  • 2010-09-14
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
相关资源
最近更新 更多