我正在使用相对较大的data.table
数据集并尝试分析/优化代码。我正在使用Rprof
,但我注意到在setkey操作中花费的大部分时间都没有包含在Rprof摘要中。有没有办法把这个时间花在一起?
这是一个小测试,显示如何在Rprof摘要中表示为数据表设置密钥所花费的时间:
创建一个测试函数,在数据表上运行配置文件的setkey操作:
testFun <- function(testTbl) {
Rprof()
setkey(testTbl, x, y, z)
Rprof(NULL)
print(summaryRprof())
}
然后创建一个足够大的测试数据表来感受setkey操作的权重:
testTbl = data.table(x=sample(1:1e7, 1e7), y=sample(1:1e7,1e7), z=sample(1:1e7,1e7))
然后运行代码,并将其包装在system.time操作中,以显示system.time总时间与rprof总时间之间的差异:
> system.time(testFun(testTbl))
$by.self
self.time self.pct total.time total.pct
"sort.list" 0.88 75.86 0.88 75.86
"<Anonymous>" 0.08 6.90 1.00 86.21
"regularorder1" 0.08 6.90 0.92 79.31
"radixorder1" 0.08 6.90 0.12 10.34
"is.na" 0.02 1.72 0.02 1.72
"structure" 0.02 1.72 0.02 1.72
$by.total
total.time total.pct self.time self.pct
"setkey" 1.16 100.00 0.00 0.00
"setkeyv" 1.16 100.00 0.00 0.00
"system.time" 1.16 100.00 0.00 0.00
"testFun" 1.16 100.00 0.00 0.00
"fastorder" 1.14 98.28 0.00 0.00
"tryCatch" 1.14 98.28 0.00 0.00
"tryCatchList" 1.14 98.28 0.00 0.00
"tryCatchOne" 1.14 98.28 0.00 0.00
"<Anonymous>" 1.00 86.21 0.08 6.90
"regularorder1" 0.92 79.31 0.08 6.90
"sort.list" 0.88 75.86 0.88 75.86
"radixorder1" 0.12 10.34 0.08 6.90
"doTryCatch" 0.12 10.34 0.00 0.00
"is.na" 0.02 1.72 0.02 1.72
"structure" 0.02 1.72 0.02 1.72
"is.unsorted" 0.02 1.72 0.00 0.00
"simpleError" 0.02 1.72 0.00 0.00
$sample.interval
[1] 0.02
$sampling.time
[1] 1.16
user system elapsed
31.112 0.211 31.101
请注意1.16和31.101的时差。
阅读?Rprof,我明白为什么会出现这种差异:
只有在放置a时,功能才会记录在配置文件日志中 调用堆栈上的上下文(请参阅sys.calls)。一些原始功能 不这样做:特别是“特殊”类型的那些(参见'R 内部手册了解更多详情。)
这就是为什么在setkey操作中花费的时间没有在Rprof中表示的原因?是否有一个解决方法让Rprof观察所有data.table的操作(包括setkey,以及其他我没有注意到的)?我基本上希望system.time和Rprof时间匹配。
这是最可能相关的sessionInfo():
> sessionInfo()
R version 3.0.2 (2013-09-25)
Platform: x86_64-apple-darwin10.8.0 (64-bit)
data.table_1.8.11
当Rprof()不在函数调用中时,我仍然会注意到这个问题:
> testFun <- function(testTbl) {
+ setkey(testTbl, x, y, z)
+ }
> Rprof()
> system.time(testFun(testTbl))
user system elapsed
28.855 0.191 28.854
> Rprof(NULL)
> summaryRprof()
$by.self
self.time self.pct total.time total.pct
"sort.list" 0.86 71.67 0.88 73.33
"regularorder1" 0.08 6.67 0.92 76.67
"<Anonymous>" 0.06 5.00 0.98 81.67
"radixorder1" 0.06 5.00 0.10 8.33
"gc" 0.06 5.00 0.06 5.00
"proc.time" 0.04 3.33 0.04 3.33
"is.na" 0.02 1.67 0.02 1.67
"sys.function" 0.02 1.67 0.02 1.67
$by.total
total.time total.pct self.time self.pct
"system.time" 1.20 100.00 0.00 0.00
"setkey" 1.10 91.67 0.00 0.00
"setkeyv" 1.10 91.67 0.00 0.00
"testFun" 1.10 91.67 0.00 0.00
"fastorder" 1.08 90.00 0.00 0.00
"tryCatch" 1.08 90.00 0.00 0.00
"tryCatchList" 1.08 90.00 0.00 0.00
"tryCatchOne" 1.08 90.00 0.00 0.00
"<Anonymous>" 0.98 81.67 0.06 5.00
"regularorder1" 0.92 76.67 0.08 6.67
"sort.list" 0.88 73.33 0.86 71.67
"radixorder1" 0.10 8.33 0.06 5.00
"doTryCatch" 0.10 8.33 0.00 0.00
"gc" 0.06 5.00 0.06 5.00
"proc.time" 0.04 3.33 0.04 3.33
"is.na" 0.02 1.67 0.02 1.67
"sys.function" 0.02 1.67 0.02 1.67
"formals" 0.02 1.67 0.00 0.00
"is.unsorted" 0.02 1.67 0.00 0.00
"match.arg" 0.02 1.67 0.00 0.00
$sample.interval
[1] 0.02
$sampling.time
[1] 1.2
EDIT2:在我的机器上只有加载了data.table包的1.8.10也有同样的问题。即使Rprof()调用不在函数内,时间也不相等:
> library(data.table)
data.table 1.8.10 For help type: help("data.table")
> base::source("/tmp/r-plugin-claytonstanley/Rsource-86075-preProcess.R", echo=TRUE)
> testFun <- function(testTbl) {
+ setkey(testTbl, x, y, z)
+ }
> testTbl = data.table(x=sample(1:1e7, 1e7), y=sample(1:1e7,1e7), z=sample(1:1e7,1e7))
> Rprof()
> system.time(testFun(testTbl))
user system elapsed
29.516 0.281 29.760
> Rprof(NULL)
> summaryRprof()
EDIT3:即使setkey
不在函数中也不起作用:
> library(data.table)
data.table 1.8.10 For help type: help("data.table")
> testTbl = data.table(x=sample(1:1e7, 1e7), y=sample(1:1e7,1e7), z=sample(1:1e7,1e7))
> Rprof()
> setkey(testTbl, x, y, z)
> Rprof(NULL)
> summaryRprof()
EDIT4:即使从--vanilla
裸机终端提示符调用R也不起作用。
EDIT5:在Linux VM上测试时是否有效。但对我来说仍然不适用于达尔文机器。
EDIT6:在看到Rprof.out文件被创建后不起作用,因此它不是写访问问题。
EDIT7:从源代码编译data.table并创建新的临时用户并在该帐户上运行后不起作用。
EDIT8:从darwin通过MacPorts编译R 3.0.2时不起作用。
EDIT9:可以在不同的darwin机器上运行,Macbook Pro笔记本电脑运行相同的操作系统版本(10.6.8)。仍然无法在运行相同操作系统版本,R版本,data.table版本等的MacPro台式机上运行。
我认为桌面计算机是以64位内核模式(非默认)运行的,而笔记本电脑是32位(默认)。 确认
答案 0 :(得分:4)
好问题。鉴于编辑,我不确定,不能重现。暂时留下答案的其余部分。
我已经在我的(非常慢的)上网本上进行了测试,它运行正常,请参阅下面的输出。
我现在可以告诉你为什么setkey
在这个测试用例上这么慢。当级别数量很大(此处大于100,000)时,它将恢复为比较排序而不是计数排序。如果你在实践中有这样的数据,那是非常差的。通常,我们在第一列中有不到100,000个唯一值,比如第二列中的日期。可以使用计数排序对两列进行排序,并且性能良好。
这是一个众所周知的问题,我们一直在努力。 Arun已经为范围> 1的整数实现了基数排序。 100,000以解决这个问题,这是在下一个版本中。 但我们仍在整理v1.8.11。请参阅我们在科隆的演示文稿,其中详细介绍了加速度。
Inroduction to data.table and news from v1.8.11
以下是v1.8.10的输出,以及R版本和lscpu
信息(供您娱乐)。我喜欢在一台带有小缓存的非常差的机器上进行测试,这样在开发过程中我可以看到当数据在具有更大缓存的大型机器上扩展时可能会有什么问题。
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 2
On-line CPU(s) list: 0,1
Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: AuthenticAMD
CPU family: 20
Model: 2
Stepping: 0
CPU MHz: 800.000
BogoMIPS: 1995.01
Virtualisation: AMD-V
L1d cache: 32K
L1i cache: 32K
L2 cache: 512K
NUMA node0 CPU(s): 0,1
$ R
R version 3.0.2 (2013-09-25) -- "Frisbee Sailing"
Copyright (C) 2013 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
> require(data.table)
Loading required package: data.table
data.table 1.8.10 For help type: help("data.table")
> testTbl = data.table(x=sample(1:1e7, 1e7), y=sample(1:1e7,1e7), z=sample(1:1e7,1e7))
> testTbl
x y z
1: 1748920 6694402 7501082
2: 4571252 565976 5695727
3: 1284455 8282944 7706392
4: 8452994 8765774 6541097
5: 6429283 329475 5271154
---
9999996: 2019750 5956558 1735214
9999997: 1096888 1657401 3519573
9999998: 1310171 9002746 350394
9999999: 5393125 5888350 7657290
10000000: 2210918 7577598 5002307
> Rprof()
> setkey(testTbl, x, y, z)
> Rprof(NULL)
> summaryRprof()
$by.self
self.time self.pct total.time total.pct
"sort.list" 195.44 91.34 195.44 91.34
".Call" 5.38 2.51 5.38 2.51
"<Anonymous>" 4.32 2.02 203.62 95.17
"radixorder1" 4.32 2.02 4.74 2.22
"regularorder1" 4.28 2.00 199.30 93.15
"is.na" 0.12 0.06 0.12 0.06
"any" 0.10 0.05 0.10 0.05
$by.total
total.time total.pct self.time self.pct
"setkey" 213.96 100.00 0.00 0.00
"setkeyv" 213.96 100.00 0.00 0.00
"fastorder" 208.36 97.38 0.00 0.00
"tryCatch" 208.36 97.38 0.00 0.00
"tryCatchList" 208.36 97.38 0.00 0.00
"tryCatchOne" 208.36 97.38 0.00 0.00
"<Anonymous>" 203.62 95.17 4.32 2.02
"regularorder1" 199.30 93.15 4.28 2.00
"sort.list" 195.44 91.34 195.44 91.34
".Call" 5.38 2.51 5.38 2.51
"radixorder1" 4.74 2.22 4.32 2.02
"doTryCatch" 4.74 2.22 0.00 0.00
"is.unsorted" 0.22 0.10 0.00 0.00
"is.na" 0.12 0.06 0.12 0.06
"any" 0.10 0.05 0.10 0.05
$sample.interval
[1] 0.02
$sampling.time
[1] 213.96
>
答案 1 :(得分:3)
问题是darwin机器运行的是带有64位内核的Snow Leopard,这不是OS X版本的默认设置。
我还验证了这对于运行Mountain Lion的另一台darwin机器来说不是问题,它默认使用64位内核。所以这是Snow Leopard与专门运行64位内核之间的交互。
作为旁注,R的官方OS X二进制安装程序仍然使用Snow Leopard构建,所以我认为这个问题仍然相关,因为Snow Leopard仍然是一个广泛使用的OS X版本。
当启用Snow Leopard中的64位内核时,不会加载仅与32位内核兼容的内核扩展。在为Snow Leopard引导到默认的32位内核之后,kextfind显示这些仅32位内核扩展在计算机上并且(很可能)已加载:
$ kextfind -not -arch x86_64
/System/Library/Extensions/ACard6280ATA.kext
/System/Library/Extensions/ACard62xxM.kext
/System/Library/Extensions/ACard67162.kext
/System/Library/Extensions/ACard671xSCSI.kext
/System/Library/Extensions/ACard6885M.kext
/System/Library/Extensions/ACard68xxM.kext
/System/Library/Extensions/AppleIntelGMA950.kext
/System/Library/Extensions/AppleIntelGMAX3100.kext
/System/Library/Extensions/AppleIntelGMAX3100FB.kext
/System/Library/Extensions/AppleIntelIntegratedFramebuffer.kext
/System/Library/Extensions/AppleProfileFamily.kext/Contents/PlugIns/AppleIntelYonahProfile.kext
/System/Library/Extensions/IO80211Family.kext/Contents/PlugIns/AirPortAtheros.kext
/System/Library/Extensions/IONetworkingFamily.kext/Contents/PlugIns/AppleRTL8139Ethernet.kext
/System/Library/Extensions/IOSerialFamily.kext/Contents/PlugIns/InternalModemSupport.kext
/System/Library/Extensions/IOSerialFamily.kext/Contents/PlugIns/MotorolaSM56KUSB.kext
/System/Library/Extensions/JMicronATA.kext
/System/Library/Extensions/System.kext/PlugIns/BSDKernel6.0.kext
/System/Library/Extensions/System.kext/PlugIns/IOKit6.0.kext
/System/Library/Extensions/System.kext/PlugIns/Libkern6.0.kext
/System/Library/Extensions/System.kext/PlugIns/Mach6.0.kext
/System/Library/Extensions/System.kext/PlugIns/System6.0.kext
/System/Library/Extensions/ufs.kext
因此,可以使用任何一个加载的扩展来为Rprof包启用某些内容,以便正确分析data.table中的setkey操作。
如果有人想进一步调查,深入挖掘一下,找到问题的根本原因,请发一个答案,我很乐意接受这个问题。