我正在使用1423657324
行和14
列的data.table。
有一个整数组( grp
),具有3790个唯一值。
当我执行以下操作时
stats <- ft[, .(
col1 = median(col1, na.rm = TRUE),
col2 = median(col2, na.rm = TRUE),
col3 = median(col3, na.rm = TRUE)
), keyby = grp]
发生以下错误:
Error in gforce(thisEnv, jsub, o__, f__, len__, irows) :
Internal error: Failed to allocate counts or TMP when assigning g in gforce
当使用相同的聚合完成较短版本的数据(大小的1/3)时,不会发生这种情况。
我可以想象median
可能会非常消耗内存,这就是为什么您通常在“大数据” SQL中看到approx_quantile
且中位数本身被完全丢弃的原因。
如果尝试按col1
对数据进行排序,是否会遇到相同的问题? 如果不是,则可能是gmedian
试图一次完成所有三列。
解决方法是,执行ft[ , .N, keyby = .(grp, col1)]
并从频率表中获取中位数,因为您说的唯一值要少得多。
将median
更改stats::median
有所帮助吗? 它应防止data.table
用gforce
优化。
禁用gforce或使用stats::median
不会触发此错误。 但是我仍然很好奇为什么会发生这种情况?
我的服务器内存为1TB,应该足以处理。
stats::median(c(col1, col2, col3))
怎么样(只是检查将内存占用量增加三倍是否有影响)
stats::median(c(col1, col2, col3))
工作正常,没有发生任何特殊情况。
好吧,错误是从
但是,我也看到nrow
被声明为int
看起来它将导致1423657324 * 2的溢出...
@ renkun-ken您介意参加考试吗? 只需将数据的行数分别减少到1073741823L
/ 1073741824L
然后尝试使用原始代码即可。
我期望第一种情况(1073741823L行)有效,但第二种将失败。
我相信这就是原因。 溢出导致无限的内存分配...
Rcpp::cppFunction("size_t test(int x) {
return x*2*sizeof(int);
}")
test(1073741823L)
#> [1] 8589934584
test(1073741824L)
#> [1] 1.844674e+19
test(1423657324L)
#> [1] 1.844674e+19
由reprex软件包(v0.3.0)创建于2020-03-10
是的, 1073741823L
情况下的效果很好,而1073741824L
情况下的效果不理想。
@ renkun-ken当然,如果可以的话,可以验证PR#4297确实可以解决此问题,这将是非常不错的。
@shrektan谢谢! 我会尽快验证。
@shrektan可悲的是太难了,无法获取回购
remote: Enumerating objects: 1431, done.
remote: Counting objects: 100% (1431/1431), done.
remote: Compressing objects: 100% (181/181), done.
Timeout, server github.com not responding. KiB | 2.00 KiB/s
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
尝试了很多次但没有运气
我之前遇到过网络问题...,所以我打包了源并将其发送到您的电子邮件中(我假设您能够访问您的个人电子邮件)。
感谢您的精美包装! 昨晚我睡觉时,我的git fetch神奇地工作。
我重试了一下,可以确认该错误已通过PR修复。 干得好!
顺便说一句,您是否怀疑还有其他类似的int
问题?
这是另外60个左右在代码中具有相似模式的地方(尚未进行梳理)
grep -Enr "[^.][0-9]+\s*[*]" src --include=*.c | grep -Ev "^src/[a-z]+[.]c:[0-9]+:\s*[/][/]"
src/forder.c:260: memset(thiscounts, 0, 256*sizeof(int));
src/forder.c:380: dmask = dround ? 1 << (8*dround-1) : 0;
src/forder.c:425: memset(stat, 0, 257*sizeof(uint64_t));
src/forder.c:728: if (!TMP || !UGRP /*|| TMP%64 || UGRP%64*/) STOP(_("Failed to allocate TMP or UGRP or they weren't cache line aligned: nth=%d"), nth);
src/forder.c:1012: memcpy(my_starts, my_starts_copy, 256*sizeof(uint16_t)); // restore starting offsets
src/forder.c:1051: uint8_t *ugrps = malloc(nBatch*256*sizeof(uint8_t));
src/frank.c:93: dans[xorder[j]-1] = (2*xstart[i]+xlen[i]-1)/2.0;
src/frank.c:126: int offset = 2*xstart[i]+xlen[i]-2;
src/gsumm.c:115: int *TMP = malloc(nrow*2*sizeof(int));
src/gsumm.c:132: int *restrict my_tmp = TMP + b*2*batchSize;
src/gsumm.c:135: int *p = my_tmp + 2*my_counts[w]++;
src/gsumm.c:146: const int *restrict p = TMP + b*2*batchSize + start*2;
src/fsort.c:125: if (batchSize < 1024) batchSize = 1024; // simple attempt to work reasonably for short vector. 1024*8 = 2 4kb pages
src/fsort.c:178: (int)(nBatch*MSBsize*sizeof(R_xlen_t)/(1024*1024)),
src/fsort.c:179: (int)(nBatch*MSBsize*sizeof(R_xlen_t)/(4*1024*nBatch)),
src/assign.c:21: SETLENGTH(x,50+n*2*sizeof(void *)/4); // 1*n for the names, 1*n for the VECSXP itself (both are over allocated).
src/assign.c:575: char *s5 = (char*) malloc(strlen(tc2) + 5); //4 * '_' + \0
src/bmerge.c:496: ival.d-xval.d == rollabs /*#1007*/))
src/bmerge.c:510: xval.d-ival.d == rollabs /*#1007*/))
src/fread.c:194: char *ptr = buf + 501 * flip;
src/fread.c:282: const char *mostConsumed = start; // tests 1550* includes both 'na' and 'nan' in nastrings. Don't stop after 'na' if 'nan' can be consumed too.
src/fread.c:375: ans = (double) tp.tv_sec + 1e-9 * (double) tp.tv_nsec;
src/fread.c:379: ans = (double) tv.tv_sec + 1e-6 * (double) tv.tv_usec;
src/fread.c:434: mmp_copy = (char *)malloc((size_t)fileSize + 1/* extra \0 */);
src/fread.c:596: acc = 10*acc + digit;
src/fread.c:628: acc = 10*acc + digit;
src/fread.c:693: acc = 10*acc + digit;
src/fread.c:727: acc = 10*acc + digit;
src/fread.c:914: E = 10*E + digit;
src/fread.c:1256: int nbit = 8*sizeof(char *); // #nocov
src/fread.c:1655: if (jump0size*100*2 < sz) nJumps=100; // 100 jumps * 100 lines = 10,000 line sample
src/fread.c:1656: else if (jump0size*10*2 < sz) nJumps=10;
src/fread.c:1663: else DTPRINT(_("(%"PRIu64" bytes from row 1 to eof) / (2 * %"PRIu64" jump0size) == %"PRIu64"\n"),
src/fread.c:1664: (uint64_t)sz, (uint64_t)jump0size, (uint64_t)(sz/(2*jump0size)));
src/fread.c:1687: if (ch<lastRowEnd) ch=lastRowEnd; // Overlap when apx 1,200 lines (just over 11*100) with short lines at the beginning and longer lines near the end, #2157
src/fread.c:1823: allocnrow = clamp_szt((size_t)(bytesRead / fmax(meanLineLen - 2*sd, minLen)),
src/fread.c:1824: (size_t)(1.1*estnrow), 2*estnrow);
src/fread.c:1833: DTPRINT(_(" Initial alloc = %"PRIu64" rows (%"PRIu64" + %d%%) using bytes/max(mean-2*sd,min) clamped between [1.1*estn, 2.0*estn]\n"),
src/fread.c:1973: size_t chunkBytes = umax((size_t)(1000*meanLineLen), 1ULL/*MB*/ *1024*1024);
src/fread.c:2030: .buff8 = malloc(rowSize8 * myBuffRows + 8),
src/fread.c:2031: .buff4 = malloc(rowSize4 * myBuffRows + 4),
src/fread.c:2032: .buff1 = malloc(rowSize1 * myBuffRows + 1),
src/fread.c:2102: ctx.buff8 = realloc(ctx.buff8, rowSize8 * myBuffRows + 8);
src/fread.c:2103: ctx.buff4 = realloc(ctx.buff4, rowSize4 * myBuffRows + 4);
src/fread.c:2104: ctx.buff1 = realloc(ctx.buff1, rowSize1 * myBuffRows + 1);
src/fread.c:2453: DTPRINT(_("%8.3fs (%3.0f%%) Memory map %.3fGB file\n"), tMap-t0, 100.0*(tMap-t0)/tTot, 1.0*fileSize/(1024*1024*1024));
src/fread.c:2460: tAlloc-tColType, 100.0*(tAlloc-tColType)/tTot, (uint64_t)allocnrow, ncol, DTbytes/(1024.0*1024*1024), (uint64_t)DTi, 100.0*DTi/allocnrow);
src/fread.c:2464: tReread-tAlloc, 100.0*(tReread-tAlloc)/tTot, nJumps, nSwept, (double)chunkBytes/(1024*1024), (int)(DTi/nJumps), nth);
src/fifelse.c:167: REPROTECT(cons = eval(SEXPPTR_RO(args)[2*i], rho), Icons);
src/fifelse.c:168: REPROTECT(outs = eval(SEXPPTR_RO(args)[2*i+1], rho), Iouts);
src/fifelse.c:173: error("Argument #%d must be logical.", 2*i+1);
src/fwrite.c:376: ch += 7 + 2*!squashDateTime;
src/fwrite.c:389: ch += 8 + 2*!squashDateTime;
src/fwrite.c:614: size_t buffSize = (size_t)1024*1024*args.buffMB;
src/fwrite.c:645: size_t maxLineLen = eolLen + args.ncol*(2*(doQuote!=0) + 1/*sep*/);
src/fwrite.c:648: maxLineLen += 2*(doQuote!=0/*NA('auto') or true*/) + 1/*sep*/;
src/fwrite.c:782: if (maxLineLen*2>buffSize) { buffSize=2*maxLineLen; rowsPerBatch=2; }
src/fwrite.c:910: int used = 100*((double)(ch-myBuff))/buffSize; // percentage of original buffMB
顺便说一句,对于需要大量数据才能重现的错误,我们是否需要为其构建测试用例?
对于此错误,一个最小的可复制示例是
library(data.table)
n <- 1500000000
ngrp <- 4000
dt <- data.table(group = sample.int(ngrp, n, replace = TRUE), x = runif(n))
res <- dt[, .(
xmedian = median(x, na.rm = TRUE)
), keyby = group]
但是dt
是18GB,创建dt
花费5-10分钟。
通过摆脱随机函数,您可以得到一个更快的示例。...只需使用rep()
和c()
...实际上我确实尝试过测试。
困难在于需要大量内存...
我试过了
dt <- data.table(group = rep(seq_len(ngrp), each = n / ngrp), x = numeric(n))
和
dt <- data.table(group = rep(seq_len(ngrp), each = n / ngrp), x = rep(rnorm(1000), each = n / 1000))
两者都快得多,但不会产生错误。 👀
而不是rep(..., each =)
,删除每个。 对分组进行排序时,不使用使用TMP
的代码部分。
我遇到了类似的问题。 在Windows SQL Server(R版本3.5.2和data.table 1.12.0)中运行R脚本时,发生以下错误:
Error in forderv(ans, cols, sort = TRUE, retGrp = FALSE, order = if (decreasing) -order else order, :
Failed to allocate TMP or UGRP or they weren't cache line aligned: nth=8
Call: source ... [ -> [.data.table -> eval -> eval -> forder -> forderv
这是由以下forcer.c行调用的:
src/forder.c:728: if (!TMP || !UGRP /*|| TMP%64 || UGRP%64*/) STOP(_("Failed to allocate TMP or UGRP or they weren't cache line aligned: nth=%d"), nth);
该脚本使用on=.(Id,date>=start_date,date<=end_date)
语句连接两个数据表(X和Y),并使用by=.EACHI
进行操作。 在本地RStudio版本上运行相同的脚本时,没有错误。 您是否认为分别设置“ Id”和“ date”? “ start_date”和“ end_date”作为X和Y中的键是否可以防止整数重载? 或者,将by=.EACHI
更改keyby=.EACHI
做什么?
提前谢谢您。
您是否认为分别设置“ Id”和“ date”? “ start_date”和“ end_date”作为X和Y中的键是否可以防止整数重载? 或者,可以将by = .EACHI更改为keyby = .EACHI吗?
我没有使用R的MSSQLServer的经验,但我认为它不会解决您的问题。 尝试昂贵吗?
我尝试了一下,但没有成功。 您知道这里有什么帮助吗? 由于依赖关系有时在MSSQL中会失真,它是否必须对data.table和bit64之间的依赖关系进行某些处理?
我认为它与bit64无关,因为bit64已停止更新3年了。 我为您提供一些(有限的)建议:
data.table::setDTthreads(1L)
关闭多个线程无效。 有时,错误变为“无效的BXL流”,这可以归因于内存不足。
您是否知道错误src/forder.c:728: if (!TMP || !UGRP /*|| TMP%64 || UGRP%64*/) STOP(_("Failed to allocate TMP or UGRP or they weren't cache line aligned: nth=%d"), nth);
可能是由于缺少RAM引起的?
@ scharlatan0139是的,它的确看起来像是由于缺少RAM而引起的错误。
@shrektan ,是导入修订的正确方法是remotes :: install_github(“ Rdatatable / data.table#fix4295”)
我尝试了此操作,但收到无效的回购错误
@ Debasis5应该是
remotes::install_github("rdatatable/data.table#4297")
要么
remotes::install_github("Rdatatable/data.table@fix4295")
最有用的评论
而不是
rep(..., each =)
,删除每个。 对分组进行排序时,不使用使用TMP
的代码部分。