- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是一个小项目,用于测试 NME 在不同版本(Windows c++、Flash)下的像素级操作性能。
它使用 BitmapData.setPixel
逐个修改像素(每帧 320x240)。 C++ 构建运行在 22 FPS ,而 闪存构建运行在 ~100 FPS 左右。与闪存相比,C++ 构建的性能大幅下降的原因是什么?如何使用 C++ 构建改进代码以获得更高的 FPS?
Mandelbrot.hx
import nme.display.Sprite;
import nme.display.Bitmap;
import nme.display.BitmapData;
import nme.text.TextField;
import nme.events.Event;
import nme.events.TimerEvent;
import nme.utils.Timer;
import nme.geom.Matrix;
import nme.geom.Rectangle;
import nme.utils.ByteArray;
class Mandelbrot
{
public static function main() : Void
{
new Mandelbrot();
}
public var pixels:Array<Array<Int>>;
public var colorModifier:Int;
private var bitmapData:BitmapData;
private var bigBitmapData:BitmapData;
private var fps:TextField;
private var width:Int;
private var height:Int;
private var matrix:Matrix;
public function new()
{
width = 320; //Std.int(flash.Lib.current.stage.stageWidth/2);
height = 240; //Std.int(flash.Lib.current.stage.stageHeight/2);
var scale:Float = 2;//flash.Lib.current.stage.stageWidth/width;
matrix = new Matrix();
matrix.scale(scale, scale);
var setBitmap:Bitmap = new Bitmap();
bitmapData = new BitmapData( width , height , false , 0x000000 );
bigBitmapData = new BitmapData( nme.Lib.current.stage.stageWidth , nme.Lib.current.stage.stageHeight , false , 0x000000 );
setBitmap.bitmapData = bigBitmapData;
nme.Lib.current.addChild( setBitmap );
var maxIterations:Int = 128;
pixels = new Array();
var beforeTime = nme.Lib.getTimer();
var xtemp;
var iteration;
var x0:Float = 0;
var y0:Float = 0;
for(ix in 0...width) {
pixels[ix] = new Array();
for(iy in 0...height) {
x0 = 0;
y0 = 0;
iteration = 128;
while ( x0*x0 + y0*y0 <= 4 && iteration > 0 )
{
xtemp = x0*x0 - y0*y0 + (ix-14*5000)/50000;
y0 = 2*x0*y0 + (iy-(height/0.6))/50000;
x0 = xtemp;
iteration--;
}
pixels[ix][iy] = iteration;
}
}
var afterTime = nme.Lib.getTimer();
var tf = new TextField();
tf.width = 400;
tf.text = "Generating fractal took "+(afterTime-beforeTime)+" ms";
nme.Lib.current.addChild(tf);
fps = new TextField();
fps.width = 400;
fps.y = 10;
fps.text = "FPS: ";
nme.Lib.current.addChild(fps);
colorModifier = 2;
var timer:haxe.Timer = new haxe.Timer(10);
runLoop();
timer.run = runLoop;
}
public function runLoop() {
var r:Int=0, b:Int=0, g:Int=0;
var pixel:Int = 0;
var beforeTime = nme.Lib.getTimer();
for(iy in 0...height) {
for(ix in 0...width) {
pixel = pixels[ix][iy];
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
bitmapData.setPixel(ix, iy, (r<<16 | g<<8 | b));
}
}
bigBitmapData.draw(bitmapData, matrix, null, null, null, false);
var afterTime = nme.Lib.getTimer();
fps.text = "FPS: "+Math.round(1000/(afterTime-beforeTime));
colorModifier += 2;
if(colorModifier > 65530)
colorModifier = 0;
}
}
<?xml version="1.0" encoding="utf-8"?>
<project>
<app
file="Mandelbrot.hx"
title="Mandelbrot sample"
package="org.haxe.nme.mandelbrot"
version="1.0.0"
company="nme"
main="Mandelbrot"
/>
<window
width="640"
height="480"
orientation="landscape"
fps="60"
background="0xffffff"
resizeable="true"
hardware="true"
/>
<classpath name="." />
<haxelib name="nme" />
<ndll name="std" />
<ndll name="regexp" />
<ndll name="zlib" />
<ndll name="nme" haxelib="nme" />
<setenv name="SHOW_CONSOLE"/>
</project>
最佳答案
查看 nme.Memory
API。这个想法是创建一个具有正确大小的 ByteArray
(或从 BitmapData
获取),选择它作为当前虚拟内存空间并直接操作其字节。
使用 Flash,您将获得大约 10 倍的速度提升,并且使用 CPP 目标也应该更快。 不要忘记在 Release 模式下编译 否则方法内联将被禁用并且性能会受到很大影响。
基本用法示例(未经测试的代码):
var rect:Rectangle = bitmapData.rect;
// 32bits integer = 4 bytes
var size:Int = bitmapData.width * bitmapData.height * 4;
// The virtual memory space we'll use
var pixels:ByteArray = new ByteArray();
// CPP does not support setting the length property directly
#if (cpp) pixels.setLength(size);
#else pixels.length = size; #end
// Select the memory space (call it once, not every frame)
Memory.select(pixels);
// And in your loop set your color
// Color is in BGRA mode, nme.Memory can only be used in little endian mode.
Memory.setI32((y * width + x) * 4, color);
// When you're done, render the BitmapData
// (don't forget to reset the ByteArray position)
pixels.position = 0;
bitmapData.setPixels(rect, pixels);
ByteArray
,因为您还需要存储迭代计数。可以在主循环中优化嵌套循环,并且可以避免大量额外的索引/地址计算:
// Note the size * 2 !
// First part of the ByteArray will be used to store the iteration count,
// the second part to draw the pixels.
#if (cpp) pixels.setLength(size * 2);
#else pixels.length = size * 2; #end
Memory.select(pixels);
// First loop storing iteration count
for (iy in 0...height)
{
for (ix in 0...width)
{
// ... do some stuff ...
Memory.setI32((iy * width + ix) << 2, iteration);
}
}
// In your runLoop :
for (i in 0...(height * width))
{
// Get the iteration count
var pixel:Int = Memory.getI32(i << 2);
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
// Note that we're writing the pixel in the second part of our ByteArray
Memory.setI32(size + (i << 2), r | g << 8 | b << 16);
}
// Sets the position to the second part of our ByteArray
pixels.position = size;
bitmapData.setPixels(rect, pixels);
getVector()
类中的
setVector()
/
BitmapData
。但它确实没有那么快。
关于Haxe 和 NME : fastest method for per pixel bitmap manipulation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10157787/
idx info market po side odd unique_odd 10 927606 OU_OT 2.5 under 2.01 927606_OU
我需要删除字符串中的所有额外空格。我使用正则表达式来匹配字符串和匹配的字符串,我用其他一些替换。为了更好地理解,请参阅以下示例: 3个输入字符串: Hello, how are you? Hello
我正在尝试: python3 -m timeit -c 'len("".join([str(x) for x in range(0, 999999)]))' 10 loops, best of 3:
我需要在 Java 中比较实例"file"的两个不同文件,并希望使用快速哈希函数来完成此操作。 想法:- 散列文件 1 中的前 20 行- 散列文件 2 中的前 20 行- 比较两个哈希值,如果相等则
我需要最快和最简单的算法来找到数组中的重复数字,还应该能够知道重复的数量。 例如:如果数组是{2,3,4,5,2,4,6,2,4,7,3,8,2} 我应该能够知道有四个 2、两个 3 和三个 4。 最
MPIR 是一个非常好的库,我目前在 C++ 中使用它来处理大量数据。不幸的是,它没有任何日志功能。因此,我正在寻找 MPIR 的 mpz_class 的快速日志功能。 我们都很清楚,C++中已经提供
假设我需要将数组转换为对象,并在此过程中进行一些过滤。 我有两种方法,一种是可链接的函数方法,例如 .map、.filter 和 .reduce,另一种是循环带有老式for循环的数组并改变一个对象。
以下代码是有效的 Swift 代码,并且在禁用优化时可以正确编译。 protocol Foo { var bar: String { get set } } class BaseFoo: Fo
我的页面上有一个多级导航菜单,其中包含一个无序列表。该列表具有 menu 类,如下所示: Category 1 Category 2 Category 3
这个问题在这里已经有了答案: How to Flatten a Multidimensional Array? (30 个答案) 关闭 3 个月前。 有没有什么快速的方法可以在不运行 foreach
我有一个非常奇怪的问题。我在我的应用程序中对 NSDictionary 对象数组进行排序,但只有当应用程序从 Xcode 运行时它才能正常工作。一旦我分发应用程序并在设备上安装和运行它,排序就不再有效
我通常按以下方式在 Java 中创建一个字符串: String foo = "123456"; 但是,我的讲师坚持要我使用 format 方法形成一个字符串,如下所示: String foo = St
要将一个数字乘以 2 的任意倍数,我将对其进行多次移位。 有没有这样的技术可以在更少的周期内将数字乘以 10? 最佳答案 80286 没有桶形移位器,这是随 80386 一起引入的。根据 Micros
要将一个数字乘以 2 的任意倍数,我将对其进行多次移位。 有没有这样的技术可以在更少的周期内将数字乘以 10? 最佳答案 80286 没有桶形移位器,这是随 80386 一起引入的。根据 Micros
我们可以使用 getchar_unlocked 通过操作字符来快速读取标准输入中的整数: int scan_d() { int ip = getchar_unlocked(), ret = 0
哪些代码会更快(或更好): $this->db->set('date', 'NOW()', FALSE); 或 $data['date'] = date('Y-m-d H:i:s'); 最佳答案 一般
所以我有 2 个矩阵:每个都是 100x100。 我正在寻找计算第 3 个矩阵,使得:M3[i]=sqrt(M1[i]^2 + M2[i]^2)。 我显然可以执行 ForLoops,但我确信还有更快的
我想在 shell 中反转一个数字。我的数字值只有 2 个可能的值:1 和 0。如果我的数字是 1,我想反转为 0,如果它是 0,我想反转为 1 什么操作可以更快? 1)操作1:使用if语句 if [
我正在从非 SSL 来源加载一些图像。为了不破坏我的 SSL 证书,我必须通过这个简单的 PHP 代理页面加载它们: 这可行,但不幸的是我的加载时间很慢。 有人知道代理图像的更快方法吗? 谢谢大家!
我正在为比赛编写程序,我需要比所有其他参赛者都快。为此,我需要一些算法帮助;理想情况下,我会使用最快的算法。 对于这个问题,我得到了两件事。第一个是元组列表,每个元组恰好包含两个元素(字符串),每个元
我是一名优秀的程序员,十分优秀!