Как улучшить время выполнения генерации изображения с многопоточностью - PullRequest
1 голос
/ 22 декабря 2019

Мне интересно, почему мой код не ускоряется при увеличении количества потоков. Мое приложение генерирует выходное изображение из двух входных изображений. если я запускаю только один поток, операция занимает 28 секунд, а если я запускаю от 2 до 8 потоков, операция занимает от 52 до 48 секунд. Это фрагмент моего кода:

def StartDuboisThreading():
    global imageLeft
    global imageRight
    global anaglyphPixelArray
    anaglyphPixelArray = None
    numberOfThreads = threadSlider.get()
    width, height = imageLeft.size
    rgb_imgLeft = imageLeft.convert('RGB')
    rgb_imgRight = imageRight.convert('RGB')
    rowsPerThread = int(height / numberOfThreads)
    remainder = height % numberOfThreads
    threads = list()
    start = time.time()

    for i in range(0, numberOfThreads):
        copyImgLeft = copy.deepcopy(rgb_imgLeft)
        copyImgRight = copy.deepcopy(rgb_imgRight)
        if (i != numberOfThreads - 1):
            threads.append(ThreadWithReturnValue(target=ThreadFunctionWithArrays, args=(
                i * rowsPerThread, (i + 1) * rowsPerThread, width, copyImgLeft, copyImgRight)))
            threads[i].start()
        else:
            threads.append(ThreadWithReturnValue(target=ThreadFunctionWithArrays, args=(
                i * rowsPerThread, height, width, copyImgLeft, copyImgRight)))
            threads[i].start()

    for i in range(0, numberOfThreads):
        pixelsArray = threads[i].join()
        if anaglyphPixelArray is None:
            anaglyphPixelArray = pixelsArray
        else:
            anaglyphPixelArray = np.append(anaglyphPixelArray, pixelsArray, axis=0)

    end = time.time()
    timeElapsed = end - start
    operationTimeText.configure(text='Time of operation: ' + timeElapsed.__str__())
    CreateImage(anaglyphPixelArray)

Я сделал глубокую копию своих объектов входных изображений, потому что я подумал, что, возможно, мои потоки одновременно ссылаются на одну и ту же память, и это может сделать небольшую задержку, ноэто не сработало. Теперь у меня нет идей, почему это только замедляется с большим количеством потоков. Это моя функция потока:

def ThreadFunctionWithArrays(startPointY, endPointY, pixelsWidth, pixelsArray1, pixelsArray2):
    numberOfRows = endPointY - startPointY
    pixelArray = GenerateEmptyPartMatrix(pixelsWidth, numberOfRows)
    y = 0
    print(str(startPointY) + " " + str(endPointY))
    for j in range(startPointY, endPointY):
        for i in range(0, pixelsWidth):
            r1, g1, b1 = pixelsArray1.getpixel((i, j))
            r2, g2, b2 = pixelsArray2.getpixel((i, j))
            pixelArray[y][i] = (
                r1 * 0.4561 + g1 * 0.500484 + b1 * 0.176381 - r2 * 0.0434706 - g2 * 0.0879388 - b2 * 0.00155529,
                - r1 * 0.0400822 - g1 * 0.0378246 - b1 * 0.0157589 + r2 * 0.378476 + g2 * 0.73364 - b2 * 0.0184503,
                - r1 * 0.0152161 - g1 * 0.0205971 - b1 * 0.00546856 - r2 * 0.0721527 - g2 * 0.112961 + b2 * 1.2264)
        y +=1
    return pixelArray

А вот определение моего расширенного объекта потока:

class ThreadWithReturnValue(Thread):
    def __init__(self, *args, **kwargs):
        super(ThreadWithReturnValue, self).__init__(*args, **kwargs)

        self._return = None

    def run(self):
        if self._target is not None:
            self._return = self._target(*self._args, **self._kwargs)

    def join(self, *args, **kwargs):
        super(ThreadWithReturnValue, self).join(*args, **kwargs)

        return self._return
...