視頻的 JSL。
picpath = ""; // "D:\Chales\pic\m";
//http://www.fractalforums.com/mandelbrot-and-julia-set/good-coordinates-for-mandelbrot-zooms/
//
//Points on the boundary of the Mandelbrot set generally have the most interesting orbits. The easiest boundary points to compute are:
//
//* the spike along the negative real axis
//* the boundary of the main cardioid: r = (1 - cos(theta))/2, x = r*cos(theta)+0.25, y = r*sin(theta)
//* the boundary of the period 2 disk: r = 0.25, x = r*cos(theta)-1, y = r*sin(theta)
eps = 1.6; // slightly outside
deep = 10;
steps = 8000;
angle = 3;
scale = 2; // <<<<<<< video made with 20, very slow
xsize = 192 * scale;
ysize = 108 * scale;
diag = Sqrt( xsize ^ 2 + ysize ^ 2 );
mat = J( ysize, xsize, . );
New Window( "mandelbrot", bb = Border Box( Text Box( "wait" ) ) );
Wait( .2 );
num = 1e6;
For( t = 0, t < steps, t += 1,
If( eps > 1e-9, eps *= .997 );
deep += .3;
angle += eps / 50;
radius = (1 - Cos( angle )) / 2 + eps;
x = radius * Cos( angle ) + 0.25;
y = radius * Sin( angle );
top = y - eps;
bottom = y + eps;
left = x - eps * xsize / ysize;
right = x + eps * xsize / ysize;
d = Floor( Min( 1e5, deep ) );
Parallel Assign( {d = d}, mat[r( top, bottom ), c( left, right )] = Mandelbrot( d, 4, c, r ) );
mat = mat / d;
red = mat ^ .5;
green = mat ^ 9;
both = Loc( red :*</img> green == 1 );
red[both] = .1;
green[both] = .4;
blue = 1 - mat ^ .2;
blue[both] = .1;
img = New Image( "rgb", {red, green, blue} );
(bb << child) << delete;
bb << append( img );
num += 1;
If( picpath != "", img << saveimage( picpath || Char( num ) || ".png" ) );
bb << updatewindow;
Wait( 0 );
);
酷,第一個是最難的。 我已經使用 Blender(在內部使用 ffmpeg)而不是直接使用 ffmpeg,選擇了一條略有不同的路徑。 我放棄了對 ffmpeg 參數的一些控制(我不想花時間學習)並換取了一個非常酷的視頻序列編輯器(它有自己重要的學習曲線)。
感謝您提供有關 Parallel Assign() 的詳細信息!我的大腦在思考如何使用它。
看起來我從未記錄過這一點,我會看看我能做些什麼。
是的,它將 1..nrows 線性插值到 top..bottom。 (類似於 c、ncols、左、右)。
如果省略 (top,bottom) 位,則表達式中的 r 值將為 1..nrows。
{d = d} 部分也需要解釋。 每個線程都有自己需要引用的所有內容的副本;左側變量是工作線程的名稱,右側是主線程的名稱。 在 4-cpu 機器上,分配完成四次。 如果它恰好是您正在復制的巨大矩陣,您可能看不到性能提升。
Mandelbrot 不需要其他數據並且可以很好地縮放。 大多數真正的問題都需要從另一個數組中讀取,並且可能還需要做一些簿記。
如果你想深入了解,試試這個:
m=J(10,10,0);
x=0;
parallelassign({x=x++},m[r,c]=x);
show(x,m);
我的 8-cpu 機器產生這個:
x = 8;
米=
[ 0 1 2 3 4 5 6 7 0 1,
2 3 4 5 6 7 0 1 2 3,
4 5 6 7 0 1 2 3 4 5,
6 7 0 1 2 3 4 5 6 7,
0 1 2 3 4 5 6 7 0 1,
2 3 4 5 6 7 0 1 2 3,
4 5 6 7 0 1 2 3 4 5,
6 7 0 1 2 3 4 5 6 7,
0 1 2 3 4 5 6 7 0 1,
2 3 4 5 6 7 0 1 2 3];
當然,您不應該編寫依賴於該模式的代碼。
還要注意矩陣分配的右側可能更複雜。
m=J(400,600,0);
parallelassign({},m[r(-1,1),c(-1,1)]=(
z=sqrt(r^2+c^2);
z=if(z<.707,.707,z)-.5;
1-z; // last item in ; sequence is result
));
m=m/max(m); // for heat color
newwindow("example",newimage(heatcolor(m,"spectral")));
“z”只存在於每個線程中,每個線程都有一個單獨的副本。
That flat area, dark red, was created by the if statement那個平坦的區域,深紅色,是由 if 語句創建的
是的,您可以使用 for 語句。 除了寫入日誌之外,您不應嘗試執行任何形式的 I/O。 不製作展示盒,不更新展示盒,不讀寫磁盤文件。 如果它不崩潰,它仍然是錯誤的。
您可以使用全局變量,但它們使用互斥鎖來序列化訪問,並且代碼可能不會比非線程代碼快。
m=J(3,5,0);
global:words="";
parallelassign({},m[r(-1,1),c(-1,1)]=(
z=sqrt(r^2+c^2);
show(r+0,c+0,r+c,z); // r and c are special, use an expression
global:words||=char(z);
z=if(z<.707,.707,z)-.5;
1-z; // last item in ; sequence is result
));
show(words);
global:words 的構建順序不可預測,由不同線程的運行速度決定。
JSL 很複雜(在內部),線程也是如此。 parallelassign 函數試圖保持一切正常(例如那些副本)。 如果您找到一種方法來解決它試圖阻止您做的事情,那麼當兩個線程同時訪問它們時,您可能會破壞內部數據結構,這將導致 JMP 在某個時候崩潰。 經常保存。
哦...關於一維矩陣的最後一點注意事項:使用兩個下標! 如果您有一個 1xN 行向量並嘗試使用單個下標,則會出現一些令人困惑的情況。 使用 R,C 並忽略常量 R==1 值。
我從這個腳本中獲得了一些樂趣,做了一些修改並創建了圖像系列以轉換成視頻來製作我自己的 mandelbrot 之旅。
問題:Parallel Assign() 函數——我正在尋找它的語法參考?我在 JMP 腳本書籍中沒有看到它,但在幫助下的 JMP 腳本指南中有一個條目。我不清楚您在腳本中使用 Parallel Assign 函數做什麼。
Parallel Assign( {d = d}, mat[r( top, bottom ), c( left, right )] = Mandelbrot( d, 4, c, r ) );r(top,bottom) 和 c(left, right) 對你有什麼作用?頂部、底部、左側和右側是在腳本中預先確定的,以確定您正在創建的框架的坐標邊界。我假設它正在頂部、底部和左側、右側之間進行某種插值以獲得要使用的 y 和 x 坐標?某處是否有此語法的一般描述?
歡迎,並感謝! 該視頻也需要數小時才能渲染,但它是 4K 分辨率和數千幀。
我開始創作GKS 80年代的節目。渲染一個分形需要數小時的 microVAX 計算時間。感謝分享。