U++ framework
Do not panic. Ask here before giving up.

Home » Community » U++ community news and announcements » Painter refactored/optimized
Painter refactored/optimized [message #50488] Sun, 11 November 2018 13:47 Go to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
After upgrading to 8C/16T machine, I was ashamed by pitiful gains (and terrible losses in some cases) of Painter performance in MT mode.

Which lead me to spending about 80 hours trying to optimize it. The result is about 10% improvement in ST performance and substantial improvements in MT - usually about 50%, but in some cases 200%. In some cases MT is now 6x faster than ST (on 8C/16T AMD 2700X).

Enjoy Smile

Mirek
Re: Painter refactored/optimized [message #50492 is a reply to message #50488] Sun, 11 November 2018 18:06 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi Mirek!

Absolutely great news! I just can't wait to get to the office tomorrow morning to test this!

Thanks and best regards,

Tom
Re: Painter refactored/optimized [message #50493 is a reply to message #50488] Sun, 11 November 2018 18:15 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3460
Registered: August 2008
Senior Veteran
Thank you Mirek.

Best regards
IƱaki
Re: Painter refactored/optimized [message #50495 is a reply to message #50488] Sun, 11 November 2018 19:55 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1432
Registered: December 2006
Ultimate Contributor
Thank you!
Could you please fix this:
uppsrc/Painter/BufferPainter.h:325:82: warning: control reaches end of non-void function [-Wreturn-type]
        BufferPainter&     NoImageCache(bool b = true)             { ImageCache(false); }
                                                                                        ^


Regards,
Novo
Re: Painter refactored/optimized [message #50497 is a reply to message #50488] Mon, 12 November 2018 09:25 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi Mirek,

It is faster indeed, but now some segments of strokes drop out on the right edge of the view if they are partially clipped by the right edge of the view. I think the 'blanking distance' from the right edge is erroneously dependent on the scaling in the transformation being used. (I use the scaling and transformation to implement zooming, rotation and panning of vector maps.)

Another issue is that Filled text drops out in the top edge when the text touches or crosses the edge of the view. The outline (Stroked) text gets drawn until half of it is clipped from the top. (They should obviously both be drawn as long as there are any pixels visible.)

Best regards,

Tom
Re: Painter refactored/optimized [message #50498 is a reply to message #50497] Mon, 12 November 2018 09:35 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Tom1 wrote on Mon, 12 November 2018 09:25
Hi Mirek,

It is faster indeed, but now some segments of strokes drop out on the right edge of the view if they are partially clipped by the right edge of the view. I think the 'blanking distance' from the right edge is erroneously dependent on the scaling in the transformation being used. (I use the scaling and transformation to implement zooming, rotation and panning of vector maps.)

Another issue is that Filled text drops out in the top edge when the text touches or crosses the edge of the view. The outline (Stroked) text gets drawn until half of it is clipped from the top. (They should obviously both be drawn as long as there are any pixels visible.)

Best regards,

Tom


Well, thanks for testing, in fact I was hoping you will test this and half expected that there will be issues.

Do you think it would be possible to provide screenshots and/or testcase?

Are this issue apparent both in ST and MT?

Also: In Render.cpp, line 142, there is

if(pathattr.mtx_serial != preclip_mtx_serial) {

try to change that to

if(pathattr.mtx_serial != preclip_mtx_serial || 1) {

Thanks, I will try hard to resolve this as soon as possible... (if you provide testcase, it should be really soon Smile

Mirek
Re: Painter refactored/optimized [message #50499 is a reply to message #50498] Mon, 12 November 2018 09:39 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
One last thing, does it show these problems without preclip?
Re: Painter refactored/optimized [message #50500 is a reply to message #50498] Mon, 12 November 2018 09:55 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Mirek,

MT/ST does not have any effect on this.

You are absolutely right: Not using painter.PreClipDashed(); fixes both issues. (I do not use the old PreClip anymore after PreClipDashed was introduced.)

Using:
if(pathattr.mtx_serial != preclip_mtx_serial || 1) {

Fixes both issues too. Smile

Best regards,

Tom
Re: Painter refactored/optimized [message #50501 is a reply to message #50500] Mon, 12 November 2018 09:59 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
As for a testcase, my (commercial) code is complex and figuring out a testcase will take a while. I'll see what I can do. Anyway, please let me know if the above already helped you on the track...

Thanks and best regards,

Tom
Re: Painter refactored/optimized [message #50503 is a reply to message #50501] Mon, 12 November 2018 10:08 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

After all, the test case was easy: Just use PainterExamples and add sw.PreClipDashed(); right after constructing the BufferPainter in App::Paint() in main.cpp.

Then compile and run PainterExamples, select Stroke example and drag the right edge of the window to gradually cover the the contents of the example. Both the line and the stroked text will disappear before they are fully covered by the window edge.

I'll stay tuned for the fix to test. Smile

Best regards,

Tom
Re: Painter refactored/optimized [message #50505 is a reply to message #50503] Mon, 12 November 2018 11:15 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Found and fixed 3 issues, can you test please?
Re: Painter refactored/optimized [message #50512 is a reply to message #50505] Mon, 12 November 2018 11:53 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Mirek,

As far as I can see, everything renders perfectly now.

Thank you very much for your excellent work on Painter again!!

Best regards,

Tom

Re: Painter refactored/optimized [message #50514 is a reply to message #50512] Mon, 12 November 2018 11:59 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
BTW, preclipping is optimized as well. As long as you do not change transformation matrix too often, it should be significantly faster.
Re: Painter refactored/optimized [message #50516 is a reply to message #50514] Mon, 12 November 2018 12:39 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

I cannot confirm any change in PreClip() or PreClipDashed() performance with my usage profile. But it is true that my program tries really hard to not pass Painter anything that would not be visible at least partially. So, this may be the reason I'm not seeing the improvement here.

Importantly, both PreClip() and PreClipDashed() still improve rendering speed of a _very_ long partially visible horizontal dashed line from e.g. 10 seconds to about 0.9 seconds. I guess the only way to dramatically improve this is to clip the line before dashing it.

Is there any difference between the two preclip functions anymore?

Best regards,

Tom
Re: Painter refactored/optimized [message #50519 is a reply to message #50516] Mon, 12 November 2018 13:25 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Tom1 wrote on Mon, 12 November 2018 12:39
Hi,

I cannot confirm any change in PreClip() or PreClipDashed() performance with my usage profile. But it is true that my program tries really hard to not pass Painter anything that would not be visible at least partially. So, this may be the reason I'm not seeing the improvement here.

Importantly, both PreClip() and PreClipDashed() still improve rendering speed of a _very_ long partially visible horizontal dashed line from e.g. 10 seconds to about 0.9 seconds. I guess the only way to dramatically improve this is to clip the line before dashing it.

Is there any difference between the two preclip functions anymore?


Yes, they basically behave the same. What is new is that inverse matrix is now calculated only if transformation matrix changes.

Mirek
Re: Painter refactored/optimized [message #50522 is a reply to message #50519] Mon, 12 November 2018 16:15 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
OK, that sounds logical. Smile

Thanks and best regards,

Tom
Re: Painter refactored/optimized [message #50523 is a reply to message #50522] Mon, 12 November 2018 23:42 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
After integrating new Painter with the target application, I have initially noticed that performance is not so great.

Investigation revealed that the problem was the app was creating BufferPainter several times per 'frame'. So in order to achive good perfromance, it is advisable to limit the number of BufferPainter destructors called. I have ended with single BufferPainter as member variable that exists for the whole lifetime of the application.

There is now new method "BufferPainter::Create" that allow it to "rebind" to another ImageBuffer, keeping as much initialized internal data as possible.
Re: Painter refactored/optimized [message #50530 is a reply to message #50523] Tue, 13 November 2018 09:14 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi Mirek,

Here's the test result from this morning.

If I replace the following in my Paint() method:
BufferPainter painter(ib);

With the following:
painter.Create(ib);

And add a class variable 'BufferPainter painter;', The rendering will seemingly randomly drop various elements, especially texts, from the result when using MT. It does not matter if I have PreClip()/PreClipDashed() enabled or not. When using ST, everything works fine even with this new Create() mechanism. Also, if I use the traditional 'BufferPainter painter(ib);' on each Paint(), everything works fine with both MT and ST.

Best regards,

Tom
Re: Painter refactored/optimized [message #50531 is a reply to message #50530] Tue, 13 November 2018 09:18 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
You have to call "Finish" at the end of rendering (that is also called by destructor). It waits for thread "pipeline" to finish the work.

Anyway, if you create single BufferPainter per render and you have thousands of polygons to render, you are probably fine. My problem was that my original code was creating like 30 BufferPainters...

Mirek
Re: Painter refactored/optimized [message #50532 is a reply to message #50531] Tue, 13 November 2018 09:35 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

OK, I added 'sw.Finish();' in the end. There is still something strange with it.

Please add 'BufferPainter csw;' to PainterExamples App and Change the App::Paint() in main.cpp:
void App::Paint(Draw& w)
{
	Size sz = GetSize();
	if(ctrl.transparent) {
		for(int y = 0; y < sz.cy; y += 32)
			for(int x = 0; x < sz.cx; x += 32)
				w.DrawRect(x, y, 32, 32, (x ^ y) & 32 ? Color(254, 172, 120) : Color(124, 135, 253));
	}
	ImageBuffer ib(sz);
	{
		//BufferPainter sw(ib, ctrl.quality); // Removed
		csw.Create(ib, ctrl.quality); // Added
		
		BufferPainter &sw=csw;
		
		if(ctrl.transparent)
			sw.Clear(RGBAZero());
		else
			sw.Clear(White());
		sw.Co(ctrl.mt);
		DoPaint(sw);
		
		sw.Finish(); // Added
	}
	w.DrawImage(0, 0, ib);
	
}


Just scaling causes strange behavior.

Best regards,

Tom

EDIT: My own code worked fine again after adding the 'sw.Finish();'. However, it feels like the transformations do not get reset to default identity transformation in PainterExamples. Maybe this should be part of Create()...?
EDIT2: This appears to solve the issue with PainterExamples. Add the following in the end of BufferPainter::Create():
pathattr.mtx = attr.mtx = Xform2D::Identity();

However, I'm not sure if this breaks something else instead...

[Updated on: Tue, 13 November 2018 10:05]

Report message to a moderator

Re: Painter refactored/optimized [message #50534 is a reply to message #50532] Tue, 13 November 2018 11:37 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Probably my bug.

Can you try to place Begin/End around DoPaint?

Mirek
Re: Painter refactored/optimized [message #50535 is a reply to message #50534] Tue, 13 November 2018 11:52 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Yes. Begin()/End() around DoPaint(); equally fixes the issue with PainterExamples. But I think it would be nice to have a clean table after BufferPainter::Create()... Of course, I understand that each re-initialized variable increases the cost towards full constructor/destructor pair.

Best regards,

Tom
Re: Painter refactored/optimized [message #50536 is a reply to message #50535] Tue, 13 November 2018 11:55 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Sure, I agree, I justed wanted hints about the problem...
Re: Painter refactored/optimized [message #50537 is a reply to message #50536] Tue, 13 November 2018 12:22 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Please test (trunk).
Re: Painter refactored/optimized [message #50538 is a reply to message #50537] Tue, 13 November 2018 12:50 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
The issue is still there in SVN 12531 if you do my above changes to PainterExamples. (Obviously, adding Begin/End will still remove the issue.)

I can't figure out what exactly you changed in Create though. Or am I working on a completely wrong SVN version?

Best regards,

Tom
Re: Painter refactored/optimized [message #50539 is a reply to message #50538] Tue, 13 November 2018 13:54 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
rev 12531:

void BufferPainter::Create(ImageBuffer& ib, int mode_)
{
	ip = &ib;

	if(mode_ != mode || (Size)size != ib.GetSize()) {
		mode = mode_;

		rasterizer.Create(ib.GetWidth(), ib.GetHeight(), mode == MODE_SUBPIXEL);
		paths.Alloc(BATCH_SIZE);
		path_info = paths;

		ClearPath();

		render_cx = ib.GetWidth();
		if(mode == MODE_SUBPIXEL) {
			render_cx *= 3;
			subpixel.Alloc(render_cx + 30);
		}
		size = ib.GetSize();
	}

	Attr& a = attr;
	a.cap = LINECAP_BUTT;
	a.join = LINEJOIN_MITER;
	a.miter_limit = 4;
	a.evenodd = false;
	a.hasclip = false;
	a.cliplevel = 0;
	a.opacity = 1;
	a.dash = NULL;
	a.mask = false;
	a.invert = false;
	a.mtx_serial = 0;

	gradientn = Null;

	jobcount = fillcount = 0;
	cojob.Clear();
	cofill.Clear();

	attrstack.Clear();
	clip.Clear();
	mask.Clear();
	onpathstack.Clear();
	pathlenstack.Clear();
	onpath.Clear();

	preclip_mtx_serial = -1;
	path_index = 0;
}
Re: Painter refactored/optimized [message #50540 is a reply to message #50539] Tue, 13 November 2018 14:06 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
OK, the file was correctly updated. (Reverting my changes simultaneously slightly misguided me to believe otherwise.)

Anyway the problem is still there: The transformation matrix does not get reset to identity in Create.

Best regards,

Tom
Re: Painter refactored/optimized [message #50541 is a reply to message #50540] Tue, 13 November 2018 16:23 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Tom1 wrote on Tue, 13 November 2018 14:06
OK, the file was correctly updated. (Reverting my changes simultaneously slightly misguided me to believe otherwise.)

Anyway the problem is still there: The transformation matrix does not get reset to identity in Create.

Best regards,

Tom


What now?


void BufferPainter::Create(ImageBuffer& ib, int mode_)
{
	ip = &ib;
	
	if(mode_ != mode || (Size)size != ib.GetSize()) {
		mode = mode_;
	
		rasterizer.Create(ib.GetWidth(), ib.GetHeight(), mode == MODE_SUBPIXEL);
	
		render_cx = ib.GetWidth();
		if(mode == MODE_SUBPIXEL) {
			render_cx *= 3;
			subpixel.Alloc(render_cx + 30);
		}
		size = ib.GetSize();
	}

	if(!paths)
		paths.Alloc(BATCH_SIZE);

	path_info = paths;

	ClearPath();

	Attr& a = attr;
	a.cap = LINECAP_BUTT;
	a.join = LINEJOIN_MITER;
	a.miter_limit = 4;
	a.evenodd = false;
	a.hasclip = false;
	a.cliplevel = 0;
	a.opacity = 1;
	a.dash = NULL;
	a.mask = false;
	a.invert = false;
	a.mtx_serial = 0;
	
	gradientn = Null;
	
	jobcount = fillcount = 0;
	cojob.Clear();
	cofill.Clear();

	attrstack.Clear();
	clip.Clear();
	mask.Clear();
	onpathstack.Clear();
	pathlenstack.Clear();
	onpath.Clear();

	preclip_mtx_serial = -1;
	path_index = 0;
}
Re: Painter refactored/optimized [message #50542 is a reply to message #50541] Tue, 13 November 2018 17:23 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

EDIT: Sorry, I did not pick up the changes yet. Please stand by. I will test these latest changes in the morning at the office.

Best regards,

Tom

[Updated on: Tue, 13 November 2018 18:29]

Report message to a moderator

Re: Painter refactored/optimized [message #50546 is a reply to message #50542] Wed, 14 November 2018 10:57 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi Mirek,

As of r12533 Create now works as expected Smile

However, there seems to be a severe performance issue with MT. In some cases MT can be three times slower than MT before this optimization round. E.g. a vector map rendering in 20 ms with previous MT and in 40 ms with ST now takes 60 ms with new MT.

This is somehow related to changing transformations (of course within Begin/End pairs) which is now extremely expensive, especially when using MT.

Thanks and best regards,

Tom

EDIT: I created a transformation intensive view that shows a matrix of just 90 symbols. Each of the symbols are drawn with strokes and fills using a different translation for each within a Begin/End pair. Rendering of this same view takes only 2.2 ms with ST but a whopping 45 ms with MT! Using PreClip or not does not have any observable effect on the result.

[Updated on: Wed, 14 November 2018 11:37]

Report message to a moderator

Re: Painter refactored/optimized [message #50547 is a reply to message #50546] Wed, 14 November 2018 13:17 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Well, thats disappointing.

I really would like to have some example so I can optimize for this case.

Mirek
Re: Painter refactored/optimized [message #50548 is a reply to message #50547] Wed, 14 November 2018 13:39 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

You can test with PainterExamples by enabling MT and running Benchmark with OnPath and OnTextPath examples.

Best regards,

Tom

EDIT: 'Pythagoras Tree Image' example portrays this slowdown too. Every other PainterExamples example running MT is on par or faster compared to ST. With my 4C8T Intel Core i7 the best MT gain is about 4x compared to ST. This is common with images and fills. Narrow geometries do not gain so much boost from MT landing at 1x-2x speed improvement.

[Updated on: Wed, 14 November 2018 14:03]

Report message to a moderator

Re: Painter refactored/optimized [message #50549 is a reply to message #50548] Wed, 14 November 2018 14:38 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Tom1 wrote on Wed, 14 November 2018 13:39
Hi,

You can test with PainterExamples by enabling MT and running Benchmark with OnPath and OnTextPath examples.

Best regards,

Tom

EDIT: 'Pythagoras Tree Image' example portrays this slowdown too. Every other PainterExamples example running MT is on par or faster compared to ST. With my 4C8T Intel Core i7 the best MT gain is about 4x compared to ST. This is common with images and fills. Narrow geometries do not gain so much boost from MT landing at 1x-2x speed improvement.


I have found that BeginOnPath was conservatively flushing rendering pipeline for no good reason, so that is now optimized out. TextOnPath is still slower if you fill the letters, that will have to wait till next batch of optimization I am afraid.

In fact, what is slow is alternating solid color / non-solid color fills - that is the case for both Pythagoras Tree Image and TextOnPath... Will have to think if there is anything I can do there...

[Updated on: Wed, 14 November 2018 14:40]

Report message to a moderator

Re: Painter refactored/optimized [message #50550 is a reply to message #50549] Wed, 14 November 2018 14:39 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
(P.S. that OnPath optimization is commited, I would be glad if you test it)
Re: Painter refactored/optimized [message #50551 is a reply to message #50550] Wed, 14 November 2018 14:56 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

Absolutely! I'm extremely motivated to help you squeeze every single extra millisecond out of the rendering times in Painter!

OnPath show now 1.4x improvement over ST and OnTextPath about 2.3x improvement... And these were over ST not over previous MT where improvement is 5x that. Well done Mirek!

A question --- removed ---

Best regards,

Tom

EDIT: Removing question. Something else is now slowing down my code. It may be related to translations (Xform2D).

[Updated on: Wed, 14 November 2018 15:07]

Report message to a moderator

Re: Painter refactored/optimized [message #50552 is a reply to message #50551] Wed, 14 November 2018 15:19 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Tom1 wrote on Wed, 14 November 2018 14:56
Hi,

Absolutely! I'm extremely motivated to help you squeeze every single extra millisecond out of the rendering times in Painter!

OnPath show now 1.4x improvement over ST and OnTextPath about 2.3x improvement... And these were over ST not over previous MT where improvement is 5x that. Well done Mirek!

A question --- removed ---

Best regards,

Tom

EDIT: Removing question. Something else is now slowing down my code. It may be related to translations (Xform2D).


Well, what is definitely slow now if you are mixing solid fills and gradient or image fills. Can that be the cause?
Re: Painter refactored/optimized [message #50553 is a reply to message #50552] Wed, 14 November 2018 15:55 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

My translated symbols are simply solid black over white background. The ST vs. MT speed ratio is about 15..20x in favor of ST. They were about equally fast when compiled against r.11960.

I need to find a pattern here. There is no clear Begin/End dependency as far as I can see. I'm trying to narrow down the code to find a test case.

Best regards,

Tom
Re: Painter refactored/optimized [message #50554 is a reply to message #50553] Wed, 14 November 2018 17:57 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
Screenshot / piece of code would be helpful (can be PM).
Re: Painter refactored/optimized [message #50557 is a reply to message #50554] Thu, 15 November 2018 10:14 Go to previous messageGo to next message
Tom1
Messages: 1319
Registered: March 2007
Ultimate Contributor
Hi,

I finally figured out a way to share this test case. I send you code and a Serialized Painting to test. (Actually, this can be quite handy for any Painter performance issue testing in general.) Here's the code:

#include <CtrlLib/CtrlLib.h>
#include <Painter/Painter.h>

using namespace Upp;

class PainterBench : public TopWindow {
public:
	Painting p;
	FileSel fs;
	
	void Open(){
		if(fs.ExecuteOpen("Select a painting to view")){
			p.Clear();
			p.Serialize(FileIn(fs.Get()));
		}
	}
	virtual bool Key(dword key, int count){
		switch(key){
			case K_CTRL_O:
				Open();
				return true;
		}
		return false;
	}
	
	typedef PainterBench CLASSNAME;

	PainterBench(){
		Sizeable();
	}
		
	virtual void Paint(Draw &draw){
		int64 STtiming=0;
		int64 MTtiming=0;
		
		ImageBuffer ib(GetSize());
		{
			BufferPainter bpainter(ib);
			bpainter.Co(true);
			bpainter.PreClipDashed();
			bpainter.Clear(White());
			bpainter.EvenOdd();
			
			int64 t0=usecs();
			bpainter.Paint(p);
			int64 t1=usecs();
			MTtiming=t1-t0;
			
		}
		{
			BufferPainter bpainter(ib);
			bpainter.Co(false);
			bpainter.PreClipDashed();
			bpainter.Clear(White());
			bpainter.EvenOdd();
			
			int64 t0=usecs();
			bpainter.Paint(p);
			int64 t1=usecs();
			STtiming=t1-t0;
			
		}
		
		SetSurface(draw,Rect(ib.GetSize()),ib,ib.GetSize(),Point(0,0));
		
		double gain=(double)STtiming/(double)(0.1+MTtiming); // Avoid div by zero
		Title(Format("Rendering MT took %lld us, ST took %lld us, MT gain is %.2f",MTtiming,STtiming,gain));
	}
};

GUI_APP_MAIN
{
	PainterBench().Run();
}


There are two Serialized painting files to test with: SomeRocks.painting exhibits the MT slowdown issue dramatically. The other file is just for checking how fast a typical map view renders.

Best regards,

Tom
Re: Painter refactored/optimized [message #50558 is a reply to message #50557] Thu, 15 November 2018 10:48 Go to previous messageGo to previous message
mirek is currently offline  mirek
Messages: 14291
Registered: November 2005
Ultimate Member
OK, so the short answer: "It is too simple"

Less short answer: Most of time is spend allocating and cleaning per-thread dynamic data. MT is using up to 128 rasterizers, each rasterizer has to be allocated (~ 256KB) and after being used, it has to be "reset". I guess there is a lot of cache misses in the process, meanwhile ST runs in L1/L2 easily.

That said, I have some tricks in my mind to be implemented to fix this. The only trouble is that it involves changes to memory allocater, which is difficult...
Previous Topic: Jsonize/Xmlize with lambda (and common template example)
Next Topic: Critical issues to resolve for U++ 2018.1 - please suggest
Goto Forum:
  


Current Time: Fri Jun 19 08:38:18 GMT+2 2026

Total time taken to generate the page: 0.01792 seconds