与Python相比,在Julia中读取csv的速度较慢

与Python相比,在Julia中读取csv的速度较慢,julia,Julia,与Python相比,在Julia中读取大型文本/csv文件需要很长时间。下面是读取大小为486.6 MB、包含153895行和644列的文件的时间 Python3.3示例 import pandas as pd import time start=time.time() myData=pd.read_csv("C:\\myFile.txt",sep="|",header=None,low_memory=False) print(time.time()-start) Output: 19.90

与Python相比,在Julia中读取大型文本/csv文件需要很长时间。下面是读取大小为486.6 MB、包含153895行和644列的文件的时间

Python3.3示例

import pandas as pd
import time
start=time.time()
myData=pd.read_csv("C:\\myFile.txt",sep="|",header=None,low_memory=False)
print(time.time()-start)

Output: 19.90
R3.0.2示例

system.time(myData<-read.delim("C:/myFile.txt",sep="|",header=F,
   stringsAsFactors=F,na.strings=""))

Output:
User    System  Elapsed
181.13  1.07    182.32
Julia 0.2.0(Julia Studio 0.4.4)示例#2

  • Julia比R快,但比Python慢。我可以采取哪些不同的措施来加快读取大型文本文件的速度

  • 另一个问题是,Julia的内存大小是硬盘文件大小的18倍,而python的内存大小仅为硬盘文件大小的2.5倍。在Matlab中,我发现它对大文件的存储效率最高,它是硬盘文件大小的2倍。Julia内存中文件太大有什么特别的原因吗


  • 最好的答案可能是我不像韦斯那样是一个好的程序员

    一般来说,数据帧中的代码没有熊猫中的代码优化得好。我相信我们可以迎头赶上,但这需要一些时间,因为我们需要首先实现很多基本功能。由于Julia中需要构建的内容太多,因此我倾向于将重点放在三个部分:(1)构建任何版本,(2)构建正确的版本,(3)构建快速、正确的版本。对于我所做的工作,Julia通常不提供任何版本的基本功能,因此我的工作重点放在(1)和(2)。随着我需要的工具越来越多,关注性能将变得更加容易

    至于内存使用,我认为答案是我们在解析表格数据时使用了一组数据结构,这比熊猫使用的效率要低得多。如果我能更好地了解Pandas的内部结构,我可以列出效率较低的地方,但现在我只能推测,一个明显的失败是我们将整个数据集读取到内存中,而不是从磁盘中获取数据块。这当然是可以避免的,而且存在这样做的问题。这只是时间问题


    注意,
    readtable
    代码相当容易阅读。要使
    的可读性更快,最确定的方法是拿出Julia profiler并开始修复它所发现的性能缺陷。

    请注意,
    @time
    的“n字节分配”输出是所有分配对象的总大小,忽略其中有多少可能已被释放。这个数字通常比内存中活动对象的最终大小高得多。我不知道这是否是您的内存大小估计的依据,但我想指出这一点。

    我发现了一些可以部分帮助这种情况的东西

  • 在Julia中使用
    readdlm()
    函数似乎比
    readtable()
    快得多(例如,在最近的一次试验中是3倍)。当然,如果需要DataFrame对象类型,则需要将其转换为DataFrame对象类型,这可能会消耗大部分或全部速度提升

  • 指定文件的尺寸可以在速度和内存分配方面产生很大的差异。我在磁盘上258.7 MB的文件中运行了此试用读取:

    julia> @time Data = readdlm("MyFile.txt", '\t', Float32, skipstart = 1);
    19.072266 seconds (221.60 M allocations: 6.573 GB, 3.34% gc time)
    
    julia> @time Data = readdlm("MyFile.txt", '\t', Float32, skipstart = 1, dims = (File_Lengths[1], 62));
    10.309866 seconds (87 allocations: 528.331 MB, 0.03% gc time)
    
  • 对象的类型规范非常重要。例如,如果数据中有字符串,那么读入的数组的数据将是Any类型,这在内存方面非常昂贵。如果内存真的是一个问题,您可能需要考虑通过先将字符串转换为整数、进行计算、然后再转换来预处理数据。此外,如果不需要太多的精度,使用Float32类型而不是Float64可以节省大量空间。在中读取文件时可以指定此选项,例如:

    Data=readdlm(“file.csv”、“file.csv”、“Float32”)

  • 关于内存使用,我特别发现,如果数据有很多重复值,PooledDataArray类型(来自DataArrays包)有助于减少内存使用。转换为这种类型的时间相对较长,因此这本身并不是一个节省时间的方法,但至少有助于在一定程度上减少内存使用。例如,加载包含1900万行和36列的数据集时,其中8列表示用于统计分析的分类变量,这将对象的内存分配从磁盘上的5倍大小减少到4倍大小。如果有更多的重复值,内存的减少可能会更加显著(我曾经遇到过PooledDataArray将内存分配减半的情况)

  • 有时,在加载和格式化数据后运行
    gc()
    (垃圾收集器)函数以清除任何不需要的ram分配也会有所帮助,尽管通常Julia会自动完成这项工作


  • 尽管如此,尽管如此,我还是期待着Julia的进一步发展,以便能够更快地加载大型数据集并更有效地使用内存。

    根据我的经验,处理较大文本文件的最佳方法不是将其加载到Julia中,而是将其流式处理。这种方法有一些额外的固定成本,但通常运行速度非常快。以下是一些伪代码:

    function streamdat()
        mycsv=open("/path/to/text.csv", "r")   # <-- opens a path to your text file
    
        sumvec = [0.0]                # <-- store a sum  here
        i = 1
        while(!eof(mycsv))            # <-- loop through each line of the file
           row = readline(mycsv) 
           vector=split(row, "|")     # <-- split each line by |
           sumvec+=parse(Float64, vector[i]) 
           i+=1
        end
    end
    
    streamdat()
    
    函数streamdat()
    
    MyCSV=打开(“/PATT/OT/TEX.CSV”,“R”)>

    Jacob Quinn有一个相对较新的朱丽亚包,称为CSV.JL,它提供了一个更快的CSV解析器,在许多情况下与大熊猫一致:

    让我们首先创建一个您正在谈论的文件来提供可重复性:

    open("myFile.txt", "w") do io
        foreach(i -> println(io, join(i+1:i+644, '|')), 1:153895)
    end
    
    现在我在Julia 1.4.2和CSV.jl 0.7.1中阅读了这个文件

    单螺纹:

    julia> @time CSV.File("myFile.txt", delim='|', header=false);
      4.747160 seconds (1.55 M allocations: 1.281 GiB, 4.29% gc time)
    
    julia> @time CSV.File("myFile.txt", delim='|', header=false);
      2.780213 seconds (13.72 k allocations: 1.206 GiB, 5.80% gc time)
    
    julia> @time CSV.File("myFile.txt", delim='|', header=false);
      1.898649 seconds (1.54 M allocations: 93.848 MiB, 1.48% gc time)
    
    julia> @time CSV.File("myFile.txt", delim='|', header=false);
      0.029965 seconds (248 allocations: 17.037 MiB)
    
    并使用例如4个螺纹:

    julia> @time CSV.File("myFile.txt", delim='|', header=false);
      4.546945 seconds (6.02 M allocations: 1.499 GiB, 5.05% gc time)
    
    julia> @time CSV.File("myFile.txt", delim='|', header=false);
      0.812742 seconds (47.28 k allocations: 1.208 GiB)
    
    在R中,它是:

    > system.time(myData<-read.delim("myFile.txt",sep="|",header=F,
    +                                stringsAsFactors=F,na.strings=""))
       user  system elapsed 
     28.615   0.436  29.048 
    
    现在,如果我们从R(速度很快)测试
    fread
    ,我们得到:

    因此,在这种情况下,总结如下:

    • 尽管在Julia中编译
      CSV.File
      的成本很高,但在第一次运行它时,它比base R或Python快得多
    • 它在速度上与R中的fread相当(在本例中稍微慢一点,但其他基准测试显示了它的情况)
      > system.time(myData<-read.delim("myFile.txt",sep="|",header=F,
      +                                stringsAsFactors=F,na.strings=""))
         user  system elapsed 
       28.615   0.436  29.048 
      
      >>> import pandas as pd
      >>> import time
      >>> start=time.time()
      >>> myData=pd.read_csv("myFile.txt",sep="|",header=None,low_memory=False)
      >>> print(time.time()-start)
      25.95710587501526
      
      > system.time(fread("myFile.txt", sep="|", header=F,
                          stringsAsFactors=F, na.strings="", nThread=1))
         user  system elapsed 
        1.043   0.036   1.082 
      > system.time(fread("myFile.txt", sep="|", header=F,
                          stringsAsFactors=F, na.strings="", nThread=4))
         user  system elapsed 
        1.361   0.028   0.416 
      
      open("myFile.txt", "w") do io
          foreach(i -> println(io, join(i+1:i+10, '|')), 1:100_000)
      end
      
      julia> @time CSV.File("myFile.txt", delim='|', header=false);
        1.898649 seconds (1.54 M allocations: 93.848 MiB, 1.48% gc time)
      
      julia> @time CSV.File("myFile.txt", delim='|', header=false);
        0.029965 seconds (248 allocations: 17.037 MiB)
      
      >>> import pandas as pd
      >>> import time
      >>> start=time.time()
      >>> myData=pd.read_csv("myFile.txt",sep="|",header=None,low_memory=False)
      >>> print(time.time()-start)
      0.07587623596191406
      
      using CSV
      @time df=CSV.read("C:/Users/hafez/personal/r/tutorial for students/Book2.csv")