Skip to content
Snippets Groups Projects
Commit 0f473913 authored by Shardul Chiplunkar's avatar Shardul Chiplunkar :squid:
Browse files

Update convolution solution (oops mainly for completeness now)

parent c122c2da
No related branches found
No related tags found
No related merge requests found
Pipeline #158001 passed
......@@ -16,13 +16,30 @@ def sequentialConvolve(
from: Int,
until: Int
): Unit = {
// Approach A, as described in the clarification announcement for this
// exercise, where we treat `from` and `until` as indices on `output`
// instead of `input` as in the given code.
var iOutput = from
while iOutput < until do
var iKernel = math.max(0, iOutput - input.length + 1)
while iKernel < kernel.length && iKernel <= iOutput do
// `output` is only ever written to between the indices `from` and
// `until`, the range of `iOutput`. The indices for `input` and
// `kernel` are computed accordingly.
output(iOutput) += input(iOutput - iKernel) * kernel(iKernel)
iKernel += 1
iOutput += 1
// ALTERNATE SOLUTION: Approach B, as described in the clarification
// announcement for this exercise, which is unchanged from the given
// code, i.e. we treat `from` and `until` as indices on `input`.
var iInput = from
while iInput < until do
var iKernel = 0
while iKernel < kernel.length do
output(iInput + iKernel) += input(iInput) * kernel(iKernel)
iKernel += 1
iInput += 1
}
def parallelConvolve(
......@@ -32,7 +49,12 @@ def parallelConvolve(
from: Int,
until: Int,
threshold: Int
): Unit =
): Unit =
// Approach A, as described in the clarification announcement for this
// exercise, where we treat `from` and `until` as indices on `output`
// instead of `input` as in the given code. This does not require us to
// change anything in this function. Only receives full credit if used
// together with Approach A for `sequentialConvolve`.
if (until - from) <= threshold then
sequentialConvolve(input, kernel, output, from, until)
else
......@@ -42,6 +64,31 @@ def parallelConvolve(
parallelConvolve(input, kernel, output, mid, until, threshold)
)
// ALTERNATE SOLUTION: Approach B, as described in the clarification
// announcement for this exercise, where we treat `from` and `until` as
// indices on `input` as in the given code. This requires up to leave a
// gap in the parallel calls to be filled in sequentially as described
// below. Only receives full credit if used together with Approach B for
// `sequentialConvolve`.
if (until - from) <= threshold then
sequentialConvolve(input, kernel, output, from, until)
else
val mid = from + (until - from) / 2
val gap = numContributeTo(input, kernel, output, mid)
// Leave a gap large enough that accesses to `output` from the first
// parallel call will not overlap with accesses from the second. This
// gap is of size equal to the number of elements of `input` that will
// contribute to the computation of the result at the lowest index of
// `output` in the second parallel call, namely, at index `mid`.
// However, we are careful not to access indices lower than `from`.
val gapBeforeMid = Math.max(from, mid - gap + 1)
parallel(
parallelConvolve(input, kernel, output, from, gapBeforeMid, threshold),
parallelConvolve(input, kernel, output, mid, until, threshold)
)
// Fill in the gap sequentially.
sequentialConvolve(input, kernel, output, gapBeforeMid, mid)
object Original_WithOutputRace:
def sequentialConvolve(
......@@ -50,15 +97,13 @@ object Original_WithOutputRace:
output: Array[Int],
from: Int,
until: Int): Unit =
var iOutput = from
while iOutput < until do
var iInput = from
while iInput < until do
var iKernel = 0
while iKernel < kernel.length do
val iInput = iOutput - iKernel
if 0 <= iInput && iInput < input.length then
output(iOutput) += input(iInput) * kernel(iKernel)
output(iInput + iKernel) += input(iInput) * kernel(iKernel)
iKernel += 1
iOutput += 1
iInput += 1
def parallelConvolve(
input: Array[Int],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment