Monte Carlo PI Simulation #2

Posted: July 26, 2010 in Simulation
Tags: , , , , , , ,

จากตัวอย่างในการทำ Graphic Simulation คราวที่แล้ว เราพบว่าการที่ต้องมาไล่คำนวนและวาดเม็ดกระสุนใหม่หมดตั้งแต่แรก ในทุก ๆ เฟรมที่แสดงผล(Render)ออกมาจะเกิดปัญหาคอขวดขึ้น โดยภาระส่วนใหญ่จะไปตกอยู่ที่การคำนวนอย่างหนักของ CPU ทำให้โปรแกรมของเราทำงานช้าลงเรื่อย ๆ
มาคราวนี้เราจะแก้ป้ญหานี้โดยเรียกใช้การแคช ซึ่งจะเก็บรายละเอียดที่วาดเสร็จแล้วไว้ใน บ่อพักข้อมูล(Buffer) เพื่อเรียกใช้งานได้อย่างรวดเร็วทันทีทันใด โดยในตัวอย่างนี้เราจะทำการแคชทุก ๆ 350 เฟรม
ทำได้โดยการดัดแปลงโค้ดดังนี้

#คำสั่งโปรแกรมภาษาไทยธอน
กล่องของฉัน = วัตถุสองมิติ.กล่องสองมิติ(1,1)
กล่องของฉัน.โหมดการวาด = GL_LINE_LOOP
กล่องของฉัน.ใช้พื้นผิว = เท็จ
วงกลมของฉัน = วัตถุสองมิติ.วงกลมสองมิติ(1)
ระยะแคช = 350

คลาส กระสุน:
	นิยาม __เริ่ม__(ตน,x,y,เข้าเป้า):
		ตน.x = x
		ตน.y = y
		ตน.เข้าเป้า = เข้าเป้า

	นิยาม วาด(ตน):
		glBegin(GL_POINTS)
		ถ้า ตน.เข้าเป้า:
			glColor3f(1.0,0.2,0.2)
		นอกจากนั้น:
			glColor3f(0.2,1.0,0.2)
		glVertex2f(ตน.x,ตน.y)
		glEnd()



คลาส หน้าต่าง(หน้าต่างกราฟฟิค):
	นิยาม เริ่มกราฟฟิค(ตน):
		ตน.เตรียมพื้นผิว(กล่องของฉัน)
		ตน.ตัวนับ = 0
		ตน.จำนวนเข้าเป้า = 0
		ตน.รายการกระสุน = []
		ตน.รายการแคช = []
	นิยาม วาดทีละมากๆ(ตน,รายการกระสุน):
		glBegin(GL_POINTS)
		แต่ละ เม็ดกระสุน ใน รายการกระสุน:
			ถ้า เม็ดกระสุน.เข้าเป้า:
				glColor3f(1.0,0.2,0.2)
			นอกจากนั้น:
				glColor3f(0.2,1.0,0.2)
			glVertex2f(เม็ดกระสุน.x,เม็ดกระสุน.y)
		glEnd()

	นิยาม วาดกราฟฟิค(ตน):
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
		glLoadIdentity()
		glTranslated(0.0, 0.0, -3.0)
		glRotatef(ตน.ตัวนับ,0.0,1.0,0.0)
		ตน.แสดงผลวัตถุ(กล่องของฉัน)
		ตน.แสดงผลวัตถุ(วงกลมของฉัน)
		x,y = ((สุ่ม()*2)-1,(สุ่ม()*2)-1)
		รัศมี = คณิต.ถอดราก(x**2 + y**2)
		ถ้า รัศมี  <= 1.0:
			เข้าเป้า = จริง
			ตน.จำนวนเข้าเป้า += 1.0
		นอกจากนั้น:
			เข้าเป้า = เท็จ
		กระสุนของฉัน = กระสุน(x,y,เข้าเป้า)
		ตน.รายการกระสุน.ต่อด้วย(กระสุนของฉัน)
		แต่ละ เม็ดกระสุน ใน ตน.รายการกระสุน:
			เม็ดกระสุน.วาด()
		ตน.ตัวนับ += 1

		ถ้า ความยาว(ตน.รายการกระสุน) == ระยะแคช:
			ตน.รายการแคช.ต่อด้วย( ตน.สร้างแคช(ตน.วาดทีละมากๆ,ตน.รายการกระสุน))
			ตน.รายการกระสุน = []

		ถ้า ความยาว(ตน.รายการแคช) > 0:
			แต่ละ แคช ใน ตน.รายการแคช:
				ตน.เรียกใช้แคช(แคช )

		ตน.เริ่มวาด()
		ตน.วาดอักษร("Monte Carlo Simulation on Thaithon" ,10,20,20,(120,250,200))
		ตน.วาดอักษร("จำนวนกระสุน : "  + ตัวหนังสือ(ตน.ตัวนับ),10,40,20,(100,200,250))
		ตน.วาดอักษร("ค่า pi ~ : "  + ตัวหนังสือ(4 * (ตน.จำนวนเข้าเป้า / ตน.ตัวนับ)),10,60,20,(100,200,250))
		ตน.จบการวาด()

หน้าต่างใหม่ = หน้าต่าง()
หน้าต่างใหม่.แสดง()

ทีนี้โปรแกรมของเราก็สามารถทำงานได้เรื่อย ๆ โดยไม่ทำให้เครื่องอืดตราบเท่าที่ Ram และ GPU(การ์ดจอ) ของเราจะรองรับได้

Share

Comments
  1. nass says:

    goooooooaaaalll

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s