dpnp icon indicating copy to clipboard operation
dpnp copied to clipboard

Issue with performance using dpnp

Open mvyasank opened this issue 2 years ago • 0 comments

The code on the dpnp using gpu or cpu devices is slower that using numpy library. But should be faster. dpnp - Device(level_zero:gpu:0) 540 ms ± 32.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) dpnp - Device(opencl:gpu:0) 731 ms ± 77.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) dpnp - Device(opencl:cpu:0) 660 ms ± 36.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) numpy 290 ms ± 16.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) The code on the dpnp:

DISPLAY_W, DISPLAY_H = 800, 600

OFFSET_X = 1.4*DISPLAY_W//2
OFFSET_Y = DISPLAY_H//2
ZOOM = 2.5/DISPLAY_H

MAX_ITER = 30

import os
os.environ["SYCL_DEVICE_FILTER"] = "level_zero:gpu"
#os.environ["SYCL_DEVICE_FILTER"] = "opencl:gpu"
#os.environ["SYCL_DEVICE_FILTER"] = "cpu"

import dpnp as np


def color_by_intensity(intensity):
    c1 = np.asarray([0.0, 0.0, 0.2])
    c2 = np.asarray([1.0, 0.7, 0.9])
    c3 = np.asarray([0.6, 1.0, 0.2])
    intensity = np.broadcast_to(intensity[:, :, np.newaxis], intensity.shape + (3,))
    return np.where(intensity < 0.5, c3*intensity + c2*(1.0-intensity), c1*intensity + c2*(1.0-intensity))

def mandelbrot(x, y, zoom):
    xx = (x - OFFSET_X) * zoom
    yy = (y - OFFSET_Y) * zoom
    c = xx + 1j * yy[:, np.newaxis]

    n_iter = np.full(c.shape, 0, dtype=np.int32)  # 2d array
    z = np.zeros(c.shape, dtype=np.complex64) # 2d array too
    mask = (n_iter < MAX_ITER)  # Initialize with True
    for i in range(MAX_ITER):
        z[mask] = z[mask]**2 + c[mask]
        mask = mask & (np.abs(z) <= 2.0)
        n_iter[mask] = i

    intensity = n_iter.T / MAX_ITER
    values = (color_by_intensity(intensity)*255).astype(np.int32)
    return values

import matplotlib.pyplot as plt
%matplotlib inline 

class Fractal:
    def __init__(self, zoom):
        self.values = np.full((DISPLAY_W, DISPLAY_H, 3), 0, dtype=np.int32)
        self.zoom = zoom
        self.x = np.linspace(0, DISPLAY_W, num=DISPLAY_W, dtype=np.float32)
        self.y = np.linspace(0, DISPLAY_H, num=DISPLAY_H, dtype=np.float32)
        print (self.x.device)

    def calculate(self):
        self.values = mandelbrot(self.x, self.y, self.zoom)

    def draw(self):
        cpu_values = np.asnumpy(self.values)
        plt.imshow(cpu_values)
            
def main():
    fractal = Fractal(ZOOM)
    %timeit fractal.calculate()
    fractal.draw()

if __name__ == "__main__":
    main()

The same code using numpy:

DISPLAY_W, DISPLAY_H = 800, 600

OFFSET_X = 1.4*DISPLAY_W//2
OFFSET_Y = DISPLAY_H//2
ZOOM = 2.5/DISPLAY_H

MAX_ITER = 30

import numpy as np

def color_by_intensity(intensity):
    c1 = np.asarray([0.0, 0.0, 0.2])
    c2 = np.asarray([1.0, 0.7, 0.9])
    c3 = np.asarray([0.6, 1.0, 0.2])
    intensity = np.broadcast_to(intensity[:, :, np.newaxis], intensity.shape + (3,))
    return np.where(intensity < 0.5, c3*intensity + c2*(1.0-intensity), c1*intensity + c2*(1.0-intensity))

def mandelbrot(x, y, zoom):
    xx = (x - OFFSET_X) * zoom
    yy = (y - OFFSET_Y) * zoom
    c = xx + 1j * yy[:, np.newaxis]

    n_iter = np.full(c.shape, 0)  # 2d array
    z = np.empty(c.shape, np.csingle)  # 2d array too
    mask = (n_iter < MAX_ITER)  # Initialize with True
    for i in range(MAX_ITER):
        z[mask] = z[mask]**2 + c[mask]
        mask = mask & (np.abs(z) <= 2.0)
        n_iter[mask] = i

    intensity = n_iter.T / MAX_ITER
    values = (color_by_intensity(intensity)*255).astype(np.int32)
    return values

import matplotlib.pyplot as plt
%matplotlib inline 

class Fractal:
    def __init__(self, zoom):
        self.values = np.full((DISPLAY_W, DISPLAY_H, 3), 0, dtype=np.int32)
        self.zoom = zoom
        #self.need_recalculate = True
        self.x = np.linspace(0, DISPLAY_W, num=DISPLAY_W, dtype=np.float32)
        self.y = np.linspace(0, DISPLAY_H, num=DISPLAY_H, dtype=np.float32)

    def calculate(self):
        self.values = mandelbrot(self.x, self.y, self.zoom)

    def draw(self):
        plt.imshow(self.values)
            
def main():
    fractal = Fractal(ZOOM)
    %timeit fractal.calculate()
    fractal.draw()

if __name__ == "__main__":
    main()

mvyasank avatar Apr 03 '23 14:04 mvyasank