使用 Timer 时 pi 计算速度变慢
Slowdown of pi calculation when Timer is used
下面的代码是我计算pi = 3.1415的代码...大约使用this公式:
use Time;
var timer = new Timer();
config const n = 10**9;
var x = 0.0, s = 0.0;
// timer.start(); // [1]_____
for k in 0 .. n {
s = ( if k % 2 == 0 then 1.0 else -1.0 ); // (-1)^k
x += s / ( 2.0 * k + 1.0 );
}
// timer.stop(); // [2]_____
// writeln( "time = ", timer.elapsed() ); // [3]_____
writef( "pi (approx) = %30.20dr\n", x * 4 );
// writef( "pi (exact) = %30.20dr\n", pi ); // [4]_____
当上面的代码编译为chpl --fast test.chpl
并执行为time ./a.out
时,则运行~4秒为
pi (approx) = 3.14159265458805059268
real 0m4.334s
user 0m4.333s
sys 0m0.006s
另一方面,如果我取消注释行 [1--3]
(使用 Timer
),程序运行速度会慢得多 ~10 秒 as
time = 10.2284
pi (approx) = 3.14159265458805059268
real 0m10.238s
user 0m10.219s
sys 0m0.018s
当我仅取消注释第 [4]
行(打印 pi 的内置值,第 [1-3]
行保持注释掉)时,同样的速度变慢:
pi (approx) = 3.14159265458805059268
pi (exact) = 3.14159265358979311600
real 0m10.144s
user 0m10.141s
sys 0m0.009s
所以我想知道为什么会出现这种减速...
我是否在上面的代码中遗漏了什么(例如 Timer
的错误用法)?
我的环境是 OSX10.11 + chapel-1.16 通过自制软件安装。
更多详情如下:
$ printchplenv --anonymize
CHPL_TARGET_PLATFORM: darwin
CHPL_TARGET_COMPILER: clang
CHPL_TARGET_ARCH: native
CHPL_LOCALE_MODEL: flat
CHPL_COMM: none
CHPL_TASKS: qthreads
CHPL_LAUNCHER: none
CHPL_TIMERS: generic
CHPL_UNWIND: none
CHPL_MEM: jemalloc
CHPL_MAKE: make
CHPL_ATOMICS: intrinsics
CHPL_GMP: gmp
CHPL_HWLOC: hwloc
CHPL_REGEXP: re2
CHPL_WIDE_POINTERS: struct
CHPL_AUX_FILESYS: none
$ clang --version
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
更新
按照建议,我按照 this and this 页面并将 CHPL_TARGET_COMPILER=gnu
添加到 ~/.chplconfig
(在 运行 make
之前)从源代码安装了 Chapel。然后,上面的所有三种情况 运行 都用了 ~4 秒。因此,问题可能与 OSX10.11 上的 clang 有关。根据评论,较新的 OSX (>= 10.12) 没有这个问题,因此升级到较新的 OSX/clang (>= 9.0) 可能就足够了。仅供参考,更新后的环境信息(使用 GNU)如下:
$ printchplenv --anonymize
CHPL_TARGET_PLATFORM: darwin
CHPL_TARGET_COMPILER: gnu +
CHPL_TARGET_ARCH: native
CHPL_LOCALE_MODEL: flat
CHPL_COMM: none
CHPL_TASKS: qthreads
CHPL_LAUNCHER: none
CHPL_TIMERS: generic
CHPL_UNWIND: none
CHPL_MEM: jemalloc
CHPL_MAKE: make
CHPL_ATOMICS: intrinsics
CHPL_GMP: none
CHPL_HWLOC: hwloc
CHPL_REGEXP: none
CHPL_WIDE_POINTERS: struct
CHPL_AUX_FILESYS: none
[--fast]
减少了 运行 次检查,但 not the issue may re-run here
请注意,setup/operation 附加开销有多大,
仅用于教育目的
(以试验并发处理),使 forall
-构造函数配备 Atomics .add()
方法,产生的开销比并发处理允许获得的开销高得多,因为在 [PAR]
启用的进程部分中的计算非常小( ref. newly re-formulated Amdahl's Law在这些太薄的 [PAR]
上-收益 v/s 确实对 [SEQ]
的附加开销太高-成本)。
一个典型的消息。
use Time;
var timer = new Timer();
config const n = 10**9;
var s = 0.0, x = 0.0;
var AtomiX: atomic real; // [AtomiX]______
AtomiX.write( 0.0 ); // [AtomiX]______
timer.start(); // [1]_____
for k in 0 .. n {
s = ( if k % 2 == 0 then 1.0 else -1.0 ); // (-1)^k
x += s / ( 2.0 * k + 1.0 );
}
/* forall k in 0..n { AtomiX.add( ( if k % 2 == 0 then 1.0 else -1.0 )
/ ( 2.0 * k + 1.0 )
); } */ // [AtomiX]______
timer.stop(); // [2]_____
writeln( "time = ", timer.elapsed() ); // [3]_____
writef( "pi (approx) = %30.20dr\n", 4 * x );
// writef( "pi (approx) = %30.20dr\n", 4 * AtimiX.read() ); // [AtomiX]______
// writef( "pi (exact) = %30.20dr\n", pi ); // [4]_____
/*
--------------------------------------------------- [--fast] // AN EMPTY RUN
time = 1e-06
Real time: 9.582 s
User time: 8.479 s
Sys. time: 0.591 s
CPU share: 94.65 %
Exit code: 0
--------------------------------------------------- [--fast] // all commented
pi (approx) = 3.14159265458805059268
Real time: 15.553 s
User time: 13.484 s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~> Timer ~ +/- 1 second ( O/S noise )
Sys. time: 0.985 s
CPU share: 93.03 %
Exit code: 0
-------------------------------------------------- [--fast ] // Timer-un-commented
time = 5.30128
time = 5.3329
pi (approx) = 3.14159265458805059268
Real time: 14.356 s
User time: 13.047 s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< Timer ~ +/- 1 second ( O/S noise )
Sys. time: 0.585 s
CPU share: 94.95 %
Exit code: 0
Real time: 16.804 s
User time: 14.853 s
Sys. time: 0.925 s
CPU share: 93.89 %
Exit code: 0
-------------------------------------------------- [--fast] // Timer-un-commented + forall + Atomics
time = 14.7406
pi (approx) = 3.14159265458805680993
Real time: 28.099 s
User time: 26.246 s
Sys. time: 0.914 s
CPU share: 96.65 %
Exit code: 0
*/
Am I missing something in the above code (e.g., wrong usage of Timer)?
不,您没有遗漏任何东西,并且正在以完全合理的方式使用 Timer
(和 Chapel)。根据我自己的实验(证实了你的实验并在你的问题下的评论中注明),这看起来是一个后端编译器问题,而不是 Chapel 或你对它的使用的基本问题。
下面的代码是我计算pi = 3.1415的代码...大约使用this公式:
use Time;
var timer = new Timer();
config const n = 10**9;
var x = 0.0, s = 0.0;
// timer.start(); // [1]_____
for k in 0 .. n {
s = ( if k % 2 == 0 then 1.0 else -1.0 ); // (-1)^k
x += s / ( 2.0 * k + 1.0 );
}
// timer.stop(); // [2]_____
// writeln( "time = ", timer.elapsed() ); // [3]_____
writef( "pi (approx) = %30.20dr\n", x * 4 );
// writef( "pi (exact) = %30.20dr\n", pi ); // [4]_____
当上面的代码编译为chpl --fast test.chpl
并执行为time ./a.out
时,则运行~4秒为
pi (approx) = 3.14159265458805059268
real 0m4.334s
user 0m4.333s
sys 0m0.006s
另一方面,如果我取消注释行 [1--3]
(使用 Timer
),程序运行速度会慢得多 ~10 秒 as
time = 10.2284
pi (approx) = 3.14159265458805059268
real 0m10.238s
user 0m10.219s
sys 0m0.018s
当我仅取消注释第 [4]
行(打印 pi 的内置值,第 [1-3]
行保持注释掉)时,同样的速度变慢:
pi (approx) = 3.14159265458805059268
pi (exact) = 3.14159265358979311600
real 0m10.144s
user 0m10.141s
sys 0m0.009s
所以我想知道为什么会出现这种减速...
我是否在上面的代码中遗漏了什么(例如 Timer
的错误用法)?
我的环境是 OSX10.11 + chapel-1.16 通过自制软件安装。 更多详情如下:
$ printchplenv --anonymize
CHPL_TARGET_PLATFORM: darwin
CHPL_TARGET_COMPILER: clang
CHPL_TARGET_ARCH: native
CHPL_LOCALE_MODEL: flat
CHPL_COMM: none
CHPL_TASKS: qthreads
CHPL_LAUNCHER: none
CHPL_TIMERS: generic
CHPL_UNWIND: none
CHPL_MEM: jemalloc
CHPL_MAKE: make
CHPL_ATOMICS: intrinsics
CHPL_GMP: gmp
CHPL_HWLOC: hwloc
CHPL_REGEXP: re2
CHPL_WIDE_POINTERS: struct
CHPL_AUX_FILESYS: none
$ clang --version
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
更新
按照建议,我按照 this and this 页面并将 CHPL_TARGET_COMPILER=gnu
添加到 ~/.chplconfig
(在 运行 make
之前)从源代码安装了 Chapel。然后,上面的所有三种情况 运行 都用了 ~4 秒。因此,问题可能与 OSX10.11 上的 clang 有关。根据评论,较新的 OSX (>= 10.12) 没有这个问题,因此升级到较新的 OSX/clang (>= 9.0) 可能就足够了。仅供参考,更新后的环境信息(使用 GNU)如下:
$ printchplenv --anonymize
CHPL_TARGET_PLATFORM: darwin
CHPL_TARGET_COMPILER: gnu +
CHPL_TARGET_ARCH: native
CHPL_LOCALE_MODEL: flat
CHPL_COMM: none
CHPL_TASKS: qthreads
CHPL_LAUNCHER: none
CHPL_TIMERS: generic
CHPL_UNWIND: none
CHPL_MEM: jemalloc
CHPL_MAKE: make
CHPL_ATOMICS: intrinsics
CHPL_GMP: none
CHPL_HWLOC: hwloc
CHPL_REGEXP: none
CHPL_WIDE_POINTERS: struct
CHPL_AUX_FILESYS: none
[--fast]
减少了 运行 次检查,但 not the issue may re-run here
请注意,setup/operation 附加开销有多大,
仅用于教育目的
(以试验并发处理),使 forall
-构造函数配备 Atomics .add()
方法,产生的开销比并发处理允许获得的开销高得多,因为在 [PAR]
启用的进程部分中的计算非常小( ref. newly re-formulated Amdahl's Law在这些太薄的 [PAR]
上-收益 v/s 确实对 [SEQ]
的附加开销太高-成本)。
一个典型的消息。
use Time;
var timer = new Timer();
config const n = 10**9;
var s = 0.0, x = 0.0;
var AtomiX: atomic real; // [AtomiX]______
AtomiX.write( 0.0 ); // [AtomiX]______
timer.start(); // [1]_____
for k in 0 .. n {
s = ( if k % 2 == 0 then 1.0 else -1.0 ); // (-1)^k
x += s / ( 2.0 * k + 1.0 );
}
/* forall k in 0..n { AtomiX.add( ( if k % 2 == 0 then 1.0 else -1.0 )
/ ( 2.0 * k + 1.0 )
); } */ // [AtomiX]______
timer.stop(); // [2]_____
writeln( "time = ", timer.elapsed() ); // [3]_____
writef( "pi (approx) = %30.20dr\n", 4 * x );
// writef( "pi (approx) = %30.20dr\n", 4 * AtimiX.read() ); // [AtomiX]______
// writef( "pi (exact) = %30.20dr\n", pi ); // [4]_____
/*
--------------------------------------------------- [--fast] // AN EMPTY RUN
time = 1e-06
Real time: 9.582 s
User time: 8.479 s
Sys. time: 0.591 s
CPU share: 94.65 %
Exit code: 0
--------------------------------------------------- [--fast] // all commented
pi (approx) = 3.14159265458805059268
Real time: 15.553 s
User time: 13.484 s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~> Timer ~ +/- 1 second ( O/S noise )
Sys. time: 0.985 s
CPU share: 93.03 %
Exit code: 0
-------------------------------------------------- [--fast ] // Timer-un-commented
time = 5.30128
time = 5.3329
pi (approx) = 3.14159265458805059268
Real time: 14.356 s
User time: 13.047 s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< Timer ~ +/- 1 second ( O/S noise )
Sys. time: 0.585 s
CPU share: 94.95 %
Exit code: 0
Real time: 16.804 s
User time: 14.853 s
Sys. time: 0.925 s
CPU share: 93.89 %
Exit code: 0
-------------------------------------------------- [--fast] // Timer-un-commented + forall + Atomics
time = 14.7406
pi (approx) = 3.14159265458805680993
Real time: 28.099 s
User time: 26.246 s
Sys. time: 0.914 s
CPU share: 96.65 %
Exit code: 0
*/
Am I missing something in the above code (e.g., wrong usage of Timer)?
不,您没有遗漏任何东西,并且正在以完全合理的方式使用 Timer
(和 Chapel)。根据我自己的实验(证实了你的实验并在你的问题下的评论中注明),这看起来是一个后端编译器问题,而不是 Chapel 或你对它的使用的基本问题。