本人电脑为双核。
使用一个进程,循环10000000次绘制2条线的时间和2个进程各循环10000000次绘制2条线的时间为什么相差这么大?
每个进程都应该有自己的地址空间,GDI对象都是在各自的进程中创建的。
本以为可以并发绘图,即便无法并发,时间比也应该是2倍啊,但是实际测试结果却有9倍之巨。求高手解疑!!!void CXXXDlg::OnBnClickedButton()
{
SYSTEMTIME time;
GetSystemTime(&time); HDC m_hScreenDC = ::GetDC(m_hWnd);
HDC m_memdc = CreateCompatibleDC(m_hScreenDC);
HBITMAP m_hBit = CreateCompatibleBitmap(m_hScreenDC,800,600);
HBITMAP m_hOldBit = (HBITMAP)SelectObject(m_memdc,m_hBit);
POINT pt; for(long i = 0;i < 10000000;i++)
{
::MoveToEx(m_memdc,0,0,&pt);
::LineTo(m_memdc,100,100);
::MoveToEx(m_memdc,200,200,&pt);
::LineTo(m_memdc,300,300);
} if(m_memdc)
{
SelectObject(m_memdc,m_hOldBit); ::DeleteDC(m_memdc);
m_memdc = NULL;
} if(m_hBit)
{
DeleteObject(m_hBit);
m_hBit = NULL;
} if(m_hScreenDC)
{
::ReleaseDC(m_hWnd,m_hScreenDC);
m_hScreenDC = NULL;
} SYSTEMTIME time2;
GetSystemTime(&time2);
CString str;
str.Format("%d-%d-%d %d-%d-%d\n",time.wMinute,time.wSecond,time.wMilliseconds,
time2.wMinute,time2.wSecond,time2.wMilliseconds);
AfxMessageBox(str);
}
使用一个进程,循环10000000次绘制2条线的时间和2个进程各循环10000000次绘制2条线的时间为什么相差这么大?
每个进程都应该有自己的地址空间,GDI对象都是在各自的进程中创建的。
本以为可以并发绘图,即便无法并发,时间比也应该是2倍啊,但是实际测试结果却有9倍之巨。求高手解疑!!!void CXXXDlg::OnBnClickedButton()
{
SYSTEMTIME time;
GetSystemTime(&time); HDC m_hScreenDC = ::GetDC(m_hWnd);
HDC m_memdc = CreateCompatibleDC(m_hScreenDC);
HBITMAP m_hBit = CreateCompatibleBitmap(m_hScreenDC,800,600);
HBITMAP m_hOldBit = (HBITMAP)SelectObject(m_memdc,m_hBit);
POINT pt; for(long i = 0;i < 10000000;i++)
{
::MoveToEx(m_memdc,0,0,&pt);
::LineTo(m_memdc,100,100);
::MoveToEx(m_memdc,200,200,&pt);
::LineTo(m_memdc,300,300);
} if(m_memdc)
{
SelectObject(m_memdc,m_hOldBit); ::DeleteDC(m_memdc);
m_memdc = NULL;
} if(m_hBit)
{
DeleteObject(m_hBit);
m_hBit = NULL;
} if(m_hScreenDC)
{
::ReleaseDC(m_hWnd,m_hScreenDC);
m_hScreenDC = NULL;
} SYSTEMTIME time2;
GetSystemTime(&time2);
CString str;
str.Format("%d-%d-%d %d-%d-%d\n",time.wMinute,time.wSecond,time.wMilliseconds,
time2.wMinute,time2.wSecond,time2.wMilliseconds);
AfxMessageBox(str);
}
绘图过程中调用过程是用的cpu,从用户地址空间到图形驱动程序,但是之后的真正的绘图过程,内部其实是使用的gpu。图形驱动程序通过显卡驱动利用cpu将用户参数传入gpu的相应寄存器,最后发送状态标志到gpu,然后挂起当前线程。gpu处理完之后会唤醒绘图线程的。绘图并不是cpu去做的比如你画一张图片,一种方法利用图片句柄调用api直接绘到dc上,另一种是利用描点函数将图片像素逐个绘到dc上。即使扣除掉调用n次描点函数的传入开销,调api还是要比像素描快n个数量级。这跟你使用多少核的cpu已经关系不大了绘图的话,尽量做到耗时的事情都化整为零,然后就是做到会同样的图形时,调用绘图api的次数越少的算法越好。最好不要去拷问cpu的性能。这样才能充分利用gpu的绘图加速功能。还一个就是为什么两个线程绘图要大大慢于一个线程绘两次图。这是因为通常情况下一个线程里一次绘制过程不会调用很多次绘图api,通常就多达几百条而已(楼主用了上千万次已经是不良设计了),然后至少是长时间的空闲(对于gpu而言)。而考虑到多数窗口程序要求快速的响应,以能尽可能好的适应人的视觉感受。图形架构都对线程内调用图形api做了优化(比如使用的缓冲线程、进程描述表,图形驱动响应客户api可以不经过io管理程序而直接与客户程序通信等技术),代价就是对于多进程同时绘图的性能大打折扣了。
2.不同的内存DC,相当于是不同的输出设备,虽然我一个进程(或者线程)调用了百万次的绘线函数(当然我这只是验证,实际项目中可不是这样的),你说“然后至少是长时间的空闲(对于gpu而言)”这个我有点疑惑。
只要你调用了绘图函数,就涉及到了gpu的访问。在xp下面,GDI使用的DC位于内存中,在vista下面也位于内存中,但是在显卡显存中有一份DC的拷贝。到了win7下面则位于显存中。仅当显存不够用时才会换页到系统内存。但是一般情况下应用程序是不用关心这些的。我也不明白你为什么放着gpu加速不愿用而非要用cpu去做。但是不管怎样,最终显示结果肯定是要靠gpu才能将画面提交到屏幕上。GDI也好、dx也好还是别的什么都一样。完全绕开gpu是不大可能的(除非你用msdos,只调用处理器int10绘图)。其他的绘图库应该也只是将那些重复的功能封装一下而已。
三维软件里的软件渲染就是这个意思
用CreateDIBSection创建一个bitmap,并且获取像素的缓冲区,可以自己画,同时可以利用各种gdi的api
没有引文这些都是现代计算机结构的知识。只要你的机器不是你自己设计的,而是PC市面上都卖的那种。不管是高端还是低端、独立显卡还是集成显卡,都是一样的结构。你非要文档的话,这些都分散在msdn的各个地方,最多的是那些api的说明里面。原理性的东西你都可以自己搜索一下。