Ускорение numpy звонков внутри Cython - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь получить быстрый код на Cython, но он на удивление медленный. Прежде всего, вот весь код:

import numpy as np
cimport numpy as np
cimport numpy.random
cimport cython

DTYPE = np.float
ctypedef np.int32_t INT32_t


cdef get_random_topleft(double maxDist, double maxAngle, double radius, double boxSize):
    cdef double angle, dist, x, y
    cdef np.ndarray[INT32_t, ndim=1] newTopLeft

    dist = np.random.rand() * maxDist
    angle = np.random.rand() * maxAngle
    newTopLeft = np.empty(2, dtype=np.int32)
    x = dist*np.cos(angle) + radius - boxSize/2
    y = dist*np.sin(angle) + radius - boxSize/2
    newTopLeft[0] = np.int32(np.round(x))
    newTopLeft[1] = np.int32(np.round(y))

    return newTopLeft


def get_random_topLefts(int numBoxes, double boxSize, double radius, double maxAngle, int seed=1337, int maxTries=50):
    cdef np.ndarray[INT32_t, ndim=2] topLefts
    cdef np.ndarray[INT32_t, ndim=1] newTopLeft
    cdef double maxDist
    cdef int outerCounter, counter, x, y, i, j, diffX, diffY, successfullyAdded
    cdef bint validSolutionFound, boxOverlaps

    np.random.seed(seed)
    maxDist = radius - np.sqrt((boxSize/2)**2 + (boxSize/2)**2)
    outerCounter = 0
    validSolutionFound = False

    while not validSolutionFound and outerCounter < maxTries:
        successfullyAdded = 0
        topLefts = np.empty((numBoxes, 2), dtype=np.int32)
        for i in range(numBoxes):
            if i == 0:
                topLefts[0, :] = get_random_topleft(maxDist, maxAngle, radius, boxSize)
                successfullyAdded += 1
            else:
                counter = 0
                while counter < 50:
                    newTopLeft = get_random_topleft(maxDist, maxAngle, radius, boxSize)
                    boxOverlaps = False
                    for j in range(i):
                        diffX = abs(np.float(newTopLeft[0] - np.float(topLefts[j, 0])))
                        diffY = abs(np.float(newTopLeft[1] - np.float(topLefts[j, 1])))

                        if diffX < boxSize and diffY < boxSize:
                            boxOverlaps = True
                            break

                    if boxOverlaps:
                        counter += 1
                    else:
                        topLefts[i, :] = newTopLeft
                        successfullyAdded += 1
                        break

        if successfullyAdded == numBoxes:
            validSolutionFound = True
        else:
            outerCounter += 1

    return validSolutionFound, topLefts

Согласно html следующие строки очень темно-желтые и требуют большого количества c -кода. Я не понимаю, почему это ... Любые подсказки?

dist = np.random.rand() * maxDist

(dist и maxDist объявлены как double)

Одновременно:

x = dist*np.cos(angle) + radius - boxSize/2

снова , dist, angle, radius, boxSize и x объявлены как двойные.

Кроме того, простое присвоение медленное ??

topLefts[i, :] = newTopLeft

topLefts объявлен как np.ndarray [INT32_t, ndim = 2] и newTopLeft as np.ndarray [INT32_t, ndim = 1]

Любая помощь будет принята с благодарностью! Большое спасибо !!

...