diff mbox

[1/5] tests/exynos: add fimg2d performance analysis

Message ID 1426890348-12807-2-git-send-email-tjakobi@math.uni-bielefeld.de (mailing list archive)
State New, archived
Headers show

Commit Message

Tobias Jakobi March 20, 2015, 10:25 p.m. UTC
Currently only fast solid color clear performance is measured.
A large buffer is allocated and solid color clear operations
are executed on it with randomly chosen properties (position
and size of the region, clear color). Execution time is
measured and output together with the amount of pixels
processed.

The 'simple' variant only executes one G2D command buffer at
a time, while the 'multi' variant executes multiple ones. This
can be used to measure setup/exec overhead.

The test also serves a stability check. If clocks/voltages are
too high or low respectively, the test quickly reveals this.

Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
---
 tests/exynos/Makefile.am          |   8 +-
 tests/exynos/exynos_fimg2d_perf.c | 245 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 252 insertions(+), 1 deletion(-)
 create mode 100644 tests/exynos/exynos_fimg2d_perf.c

Comments

Emil Velikov March 22, 2015, 3:36 p.m. UTC | #1
On 20/03/15 22:25, Tobias Jakobi wrote:
> Currently only fast solid color clear performance is measured.
> A large buffer is allocated and solid color clear operations
> are executed on it with randomly chosen properties (position
> and size of the region, clear color). Execution time is
> measured and output together with the amount of pixels
> processed.
> 
> The 'simple' variant only executes one G2D command buffer at
> a time, while the 'multi' variant executes multiple ones. This
> can be used to measure setup/exec overhead.
> 
> The test also serves a stability check. If clocks/voltages are
> too high or low respectively, the test quickly reveals this.
> 
> Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Hi Tobias,

As most of this series is quite Exynos specific I will cover the misc
bits, and leave the core part to someone familiar with the hardware.

> ---
>  tests/exynos/Makefile.am          |   8 +-
>  tests/exynos/exynos_fimg2d_perf.c | 245 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 252 insertions(+), 1 deletion(-)
>  create mode 100644 tests/exynos/exynos_fimg2d_perf.c
> 
> diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
> index b21d016..243f957 100644
> --- a/tests/exynos/Makefile.am
> +++ b/tests/exynos/Makefile.am
> @@ -5,9 +5,11 @@ AM_CFLAGS = \
>  	-I $(top_srcdir)/exynos \
>  	-I $(top_srcdir)
>  
> +bin_PROGRAMS = exynos_fimg2d_perf
> +
Might I suggest that we treat this (and your follow up utility) as a
test ? I.e. use

if HAVE_INSTALL_TESTS
bin_PROGRAMS = \
	exynos_fimg2d_perf
else
noinst_PROGRAMS = \
	exynos_fimg2d_perf
endif

and amend the block below appropriately ?

>  if HAVE_LIBKMS
>  if HAVE_INSTALL_TESTS
> -bin_PROGRAMS = \
> +bin_PROGRAMS += \
>  	exynos_fimg2d_test
>  else
>  noinst_PROGRAMS = \
> @@ -15,6 +17,10 @@ noinst_PROGRAMS = \
>  endif
>  endif
>  
> +exynos_fimg2d_perf_LDADD = \
> +	$(top_builddir)/libdrm.la \
> +	$(top_builddir)/exynos/libdrm_exynos.la
> +
>  exynos_fimg2d_test_LDADD = \
>  	$(top_builddir)/libdrm.la \
>  	$(top_builddir)/libkms/libkms.la \
> diff --git a/tests/exynos/exynos_fimg2d_perf.c b/tests/exynos/exynos_fimg2d_perf.c
> new file mode 100644
> index 0000000..f45cacc
> --- /dev/null
> +++ b/tests/exynos/exynos_fimg2d_perf.c
> @@ -0,0 +1,245 @@
Can you add a licence to this file. Would be nice if it's covered by
X/MIT so that *BSD folk and others can use your tool.

> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <time.h>
> +
> +#include <xf86drm.h>
> +
> +#include "exynos_drm.h"
> +#include "exynos_drmif.h"
> +#include "exynos_fimg2d.h"
> +
> +/* Enable to format the output so that it can be fed into Mathematica. */
> +#define OUTPUT_MATHEMATICA 0
> +
> +static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
> +			unsigned buf_width, unsigned buf_height, unsigned iterations)
> +{
> +	struct timespec tspec = { 0 };
> +	struct g2d_image img = { 0 };
> +
> +	unsigned long long g2d_time;
> +	unsigned i;
> +	int ret = 0;
> +
> +	img.width = buf_width;
> +	img.height = buf_height;
> +	img.stride = buf_width * 4;
> +	img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
> +	img.buf_type = G2D_IMGBUF_GEM;
> +	img.bo[0] = bo->handle;
> +
> +	srand(time(NULL));
> +
> +	printf("starting simple G2D performance test\n");
> +	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
> +		buf_width, buf_height, iterations);
> +
> +#if (OUTPUT_MATHEMATICA == 1)
> +	putchar('{');
> +#endif
> +
I'm suspecting that having this as a runtime option will be better.
Something like ./exynos_fimg2d_perf --output mathematica ?

As a general note I would recommend keeping statements on separate lines
(none of if (foo) far()) as it makes debugging easier.

Although all of the above are my take on things, so checks with the
Exynos crew if they feel otherwise :-)

Cheers,
Emil
Tobias Jakobi March 22, 2015, 4:35 p.m. UTC | #2
Hello Emil,


Emil Velikov wrote:
> Might I suggest that we treat this (and your follow up utility) as a
> test ? I.e. use
> 
> if HAVE_INSTALL_TESTS
> bin_PROGRAMS = \
> 	exynos_fimg2d_perf
> else
> noinst_PROGRAMS = \
> 	exynos_fimg2d_perf
> endif
> 
> and amend the block below appropriately ?
sure, honestly I don't even remember why I didn't add these as tests?
*confused*


> Can you add a licence to this file. Would be nice if it's covered by
> X/MIT so that *BSD folk and others can use your tool.
Will do! Even though I probably won't go with a MIT license.


> I'm suspecting that having this as a runtime option will be better.
> Something like ./exynos_fimg2d_perf --output mathematica ?
Well, I was thinking about removing the Mathematica specific code for
the submission, but I then left it in. I use Mathematica for parts of my
thesis, so it's usually my preferred tool to visualize data. I guess a
more 'open-source' friendly solution here would be to provide GnuPlot
output, but I guess I leave that to another use :)


> As a general note I would recommend keeping statements on separate lines
> (none of if (foo) far()) as it makes debugging easier.
OK, changing this.


With best wishes,
Tobias
Tobias Jakobi March 25, 2015, 6:27 p.m. UTC | #3
Hello,

the new version should fix most of the mentioned issues.

Tobias Jakobi wrote:
>> As a general note I would recommend keeping statements on separate lines
>> (none of if (foo) far()) as it makes debugging easier.
> OK, changing this.
Except for this, I didn't change it since I don't see the point. In fact
I think that splitting the few occurrences makes the code less readable.

I haven't worked with getopt before, so I gave it a try and made all
these hardcoded parameters configurable.

With best wishes,
Tobias
Emil Velikov March 26, 2015, 3:16 p.m. UTC | #4
On 25/03/15 18:27, Tobias Jakobi wrote:
> Hello,
> 
> the new version should fix most of the mentioned issues.
> 
> Tobias Jakobi wrote:
>>> As a general note I would recommend keeping statements on separate lines
>>> (none of if (foo) far()) as it makes debugging easier.
>> OK, changing this.
> Except for this, I didn't change it since I don't see the point. In fact
> I think that splitting the few occurrences makes the code less readable.
> 
Beauty is in the eye of the beholder.

> I haven't worked with getopt before, so I gave it a try and made all
> these hardcoded parameters configurable.
> 
Nice :-)

Cheers,
Emil
diff mbox

Patch

diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
index b21d016..243f957 100644
--- a/tests/exynos/Makefile.am
+++ b/tests/exynos/Makefile.am
@@ -5,9 +5,11 @@  AM_CFLAGS = \
 	-I $(top_srcdir)/exynos \
 	-I $(top_srcdir)
 
+bin_PROGRAMS = exynos_fimg2d_perf
+
 if HAVE_LIBKMS
 if HAVE_INSTALL_TESTS
-bin_PROGRAMS = \
+bin_PROGRAMS += \
 	exynos_fimg2d_test
 else
 noinst_PROGRAMS = \
@@ -15,6 +17,10 @@  noinst_PROGRAMS = \
 endif
 endif
 
+exynos_fimg2d_perf_LDADD = \
+	$(top_builddir)/libdrm.la \
+	$(top_builddir)/exynos/libdrm_exynos.la
+
 exynos_fimg2d_test_LDADD = \
 	$(top_builddir)/libdrm.la \
 	$(top_builddir)/libkms/libkms.la \
diff --git a/tests/exynos/exynos_fimg2d_perf.c b/tests/exynos/exynos_fimg2d_perf.c
new file mode 100644
index 0000000..f45cacc
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_perf.c
@@ -0,0 +1,245 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <xf86drm.h>
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+#include "exynos_fimg2d.h"
+
+/* Enable to format the output so that it can be fed into Mathematica. */
+#define OUTPUT_MATHEMATICA 0
+
+static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
+			unsigned buf_width, unsigned buf_height, unsigned iterations)
+{
+	struct timespec tspec = { 0 };
+	struct g2d_image img = { 0 };
+
+	unsigned long long g2d_time;
+	unsigned i;
+	int ret = 0;
+
+	img.width = buf_width;
+	img.height = buf_height;
+	img.stride = buf_width * 4;
+	img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+	img.buf_type = G2D_IMGBUF_GEM;
+	img.bo[0] = bo->handle;
+
+	srand(time(NULL));
+
+	printf("starting simple G2D performance test\n");
+	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
+		buf_width, buf_height, iterations);
+
+#if (OUTPUT_MATHEMATICA == 1)
+	putchar('{');
+#endif
+
+	for (i = 0; i < iterations; ++i) {
+		unsigned x, y, w, h;
+
+		x = rand() % buf_width;
+		y = rand() % buf_height;
+
+		if (x == (buf_width - 1))
+			x -= 1;
+		if (y == (buf_height - 1))
+			y -= 1;
+
+		w = rand() % (buf_width - x);
+		h = rand() % (buf_height - y);
+
+		if (w == 0) w = 1;
+		if (h == 0) h = 1;
+
+		img.color = rand();
+
+		ret = g2d_solid_fill(ctx, &img, x, y, w, h);
+
+		clock_gettime(CLOCK_MONOTONIC, &tspec);
+
+		if (ret == 0)
+			ret = g2d_exec(ctx);
+
+		if (ret != 0) {
+			fprintf(stderr, "error: iteration %u failed (x = %u, y = %u, w = %u, h = %u)\n",
+				i, x, y, w, h);
+			break;
+		} else {
+			struct timespec end = { 0 };
+			clock_gettime(CLOCK_MONOTONIC, &end);
+
+			g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
+			g2d_time += (end.tv_nsec - tspec.tv_nsec);
+
+#if (OUTPUT_MATHEMATICA == 1)
+			if (i != 0) putchar(',');
+			printf("{%u,%llu}", w * h, g2d_time);
+#else
+			printf("num_pixels = %u, usecs = %llu\n", w * h, g2d_time);
+#endif
+		}
+	}
+
+#if (OUTPUT_MATHEMATICA == 1)
+	printf("}\n");
+#endif
+
+	return ret;
+}
+
+static int fimg2d_perf_multi(struct exynos_bo *bo, struct g2d_context *ctx,
+			unsigned buf_width, unsigned buf_height, unsigned iterations, unsigned batch)
+{
+	struct timespec tspec = { 0 };
+	struct g2d_image *images;
+
+	unsigned long long g2d_time;
+	unsigned i, j;
+	int ret = 0;
+
+	images = calloc(batch, sizeof(struct g2d_image));
+	for (i = 0; i < batch; ++i) {
+		images[i].width = buf_width;
+		images[i].height = buf_height;
+		images[i].stride = buf_width * 4;
+		images[i].color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+		images[i].buf_type = G2D_IMGBUF_GEM;
+		images[i].bo[0] = bo->handle;
+	}
+
+	srand(time(NULL));
+
+	printf("starting multi G2D performance test (batch size = %u)\n", batch);
+	printf("buffer width = %u, buffer height = %u, iterations = %u\n",
+		buf_width, buf_height, iterations);
+
+#if (OUTPUT_MATHEMATICA == 1)
+	putchar('{');
+#endif
+
+	for (i = 0; i < iterations; ++i) {
+		unsigned num_pixels = 0;
+
+		for (j = 0; j < batch; ++j) {
+			unsigned x, y, w, h;
+
+			x = rand() % buf_width;
+			y = rand() % buf_height;
+
+			if (x == (buf_width - 1))
+				x -= 1;
+			if (y == (buf_height - 1))
+				y -= 1;
+
+			w = rand() % (buf_width - x);
+			h = rand() % (buf_height - y);
+
+			if (w == 0) w = 1;
+			if (h == 0) h = 1;
+
+			images[j].color = rand();
+
+			num_pixels += w * h;
+
+			ret = g2d_solid_fill(ctx, &images[j], x, y, w, h);
+			if (ret != 0)
+				break;
+		}
+
+		clock_gettime(CLOCK_MONOTONIC, &tspec);
+
+		if (ret == 0)
+			ret = g2d_exec(ctx);
+
+		if (ret != 0) {
+			fprintf(stderr, "error: iteration %u failed (num_pixels = %u)\n", i, num_pixels);
+			break;
+			break;
+		} else {
+			struct timespec end = { 0 };
+			clock_gettime(CLOCK_MONOTONIC, &end);
+
+			g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
+			g2d_time += (end.tv_nsec - tspec.tv_nsec);
+
+#if (OUTPUT_MATHEMATICA == 1)
+			if (i != 0) putchar(',');
+			printf("{%u,%llu}", num_pixels, g2d_time);
+#else
+			printf("num_pixels = %u, usecs = %llu\n", num_pixels, g2d_time);
+#endif
+		}
+	}
+
+#if (OUTPUT_MATHEMATICA == 1)
+	printf("}\n");
+#endif
+
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	int fd, ret;
+
+	struct exynos_device *dev;
+	struct g2d_context *ctx;
+	struct exynos_bo *bo;
+
+	ret = 0;
+
+	fd = drmOpen("exynos", NULL);
+	if (fd < 0) {
+		fprintf(stderr, "error: failed to open drm\n");
+		ret = -1;
+
+		goto out;
+	}
+
+	dev = exynos_device_create(fd);
+	if (dev == NULL) {
+		fprintf(stderr, "error: failed to create device\n");
+		ret = -2;
+
+		goto fail;
+	}
+
+	ctx = g2d_init(fd);
+	if (ctx == NULL) {
+		fprintf(stderr, "error: failed to init G2D\n");
+		ret = -3;
+
+		goto g2d_fail;
+	}
+
+	bo = exynos_bo_create(dev, 4096 * 4096 * 4, 0);
+	if (bo == NULL) {
+		fprintf(stderr, "error: failed to create bo\n");
+		ret = -4;
+
+		goto bo_fail;
+	}
+
+	ret = fimg2d_perf_simple(bo, ctx, 4096, 4096, 128);
+
+	if (ret == 0)
+		ret = fimg2d_perf_multi(bo, ctx, 4096, 4096, 128, 3);
+
+	exynos_bo_destroy(bo);
+
+bo_fail:
+	g2d_fini(ctx);
+
+g2d_fail:
+	exynos_device_destroy(dev);
+
+fail:
+	drmClose(fd);
+
+out:
+	return ret;
+}