1725600487
2024-09-06 03:22:21
怠け者のプログラマーは、プログラミングの労力をコンピューティングの労力で代替することを好むことが多い。私もまさにそのようなプログラマーだ。私の研究では、テラバイト規模の大規模なデータセットに対してアルゴリズムを設計して実行する必要があることが多い。NIHのフェローとして、私は10万以上のプロセッサを備えたクラスタであるBiowulfにアクセスできるので、1つの実験のためにシングルスレッドのパフォーマンスを最適化するために膨大な時間を費やす価値は通常ない。 マップリデュース。
これらのリソースにアクセスできるにもかかわらず、私はますます Nimプログラミング言語 データ処理タスク用。Nim は計算科学では過小評価されていますが、非数値データ処理用の Python の非常に有能な代替品です。大まかに言えば、Nim は Python と同じくらい簡単に記述でき、C と同じくらい高速です。Nim は、コンパイル言語のパフォーマンスと動的言語の表現力を兼ね備えた新しい世代の言語の 1 つです。Python を知っていれば、Nim を 90% 理解してそのメリットをすべて享受できます。
次の簡単な問題を考えてみましょう。DNA配列(A、T、G、Cの4つの文字で構成される文字列)がテキストファイルに保存されています。 > 区切られたコメント行(つまり 固定フォーマット標準的なタスクは、シーケンス内のGとCの割合を計算することです。これは、 GC含有量Python では、単純な実装は次のようになります。
gc = 0
total = 0
for line in open("orthocoronavirinae.fasta"):
if line[0] == '>': # ignore comment lines
continue
for letter in line.rstrip():
if letter == 'C' or letter == 'G':
gc += 1
total += 1
print(gc / total)
このコードは、私のラップトップで 150 MB のコロナウイルスゲノムデータセットを実行すると 23.43 秒かかります。代わりに、Nim を使用すれば、実質的に無料で大幅なスピードアップを実現できます。実際、Nim の実装はほぼ同じです。
var gc = 0
var total = 0
for line in lines("orthocoronavirinae.fasta"):
if line[0] == '>': # ignore comment lines
continue
for letter in line:
if letter == 'C' or letter == 'G':
gc += 1
total += 1
echo(gc / total)
これらの変更は、コード的には小さいですが、パフォーマンスの点では極めて大きなものです。
| プログラム | 時間 | ニムとの関係 |
|---|---|---|
| Python 3.9 | 23.43秒 | 30.6倍 |
| ピピ 7.3 | 2.54秒 | 3.3倍 |
Nim 1.4(-d:danger --gc:orc フラグ) |
0.765秒 | 1.0倍 |
比較の公平性を保つために、Nimのコンパイルプロセスにはさらに702ミリ秒かかりました。つまり、 まだ PyPyを使用するよりも、最適化されたコンパイルと実行サイクルを完全に実行するのが高速です。Nimには、 r コンパイル後にプログラムを自動的に実行するコマンドです。Nim はコンパイル言語ですが、コンパイル プロセスは十分に高速なので、インタープリタ言語の代わりに使用できます。
ほぼ同じですが、Nim コードと Python コードにはいくつかの違いがあります。
- 変数は次のように宣言されます
varNimでは実行時定数を次のように定義できます。letコンパイル時に変更の可能性がチェックされます。また、コンパイル時の定数もサポートしています。const。 - の
lines関数は、openファイルの内容を1行ずつ繰り返し処理します。lines機能の1つは、次のような改行文字を自動的に削除することです。LFそしてCRLFだからもうline.rstrip()。 - ニムは
echo、 ないprintいくつか小さな違いはありますが、echoPython 2.xの時代ですprint-as-a-statement スタイルの表現が復活しました (例えばecho "Hello world!")。
Nimがいかに便利かを説明するために、私が研究中に遭遇した実例を考えてみましょう。私のデータには回文的なアーティファクトがたくさんあり、新しい ウイロイドこれらのアーティファクトの特徴は、長いサブシーケンスとその逆補完 (サブシーケンスを逆順に並べ、各塩基を対応するペアに置き換えたもの) が存在することです。問題の範囲を測るには、データセット内の各シーケンスを調べて、アーティファクトである可能性があるかどうかを確認し、削除する必要がありました。まず、標準的な Python の方法を見てみましょう。
import sys
from Bio import SeqIO
from Bio.Seq import Seq
# iterator for subsequences of length k
def kmers(seq, k):
for i in range(len(seq) - k + 1):
yield seq[i:i+k]
for record in SeqIO.parse(sys.argv[1], "fasta"):
unique_kmers = set()
palindrome = False
for kmer in kmers(record.seq, 25):
if kmer.reverse_complement() in unique_kmers:
palindrome = True
break
unique_kmers.add(kmer)
if not palindrome:
print(record.format("fasta"))
そしてニムでは:
import os
import sets
import bioseq # my library, has k-mer iterator and FASTA parsing
for record in readFasta[Dna](paramStr(1)):
var uniqueKmers = initHashSet[Dna]()
var palindrome = false
for kmer in kmers(record, 25):
if kmer.reverseComplement() in uniqueKmers:
palindrome = true
break
uniqueKmers.incl(kmer)
if not palindrome:
echo(record.asFasta)
繰り返しますが、これらのプログラムは本質的に同一です。ここでの顕著な違いは次のとおりです。
- ニムは
paramStrアクセスするargv。 - 標準的なケーススタイルは
camelCase、 ないsnake_caseNim は、大文字 (最初の文字を除く) とアンダースコアを削除した後で同じ識別子を等しいものとして扱います。つまり、任意のスタイルを使用できます。
書くのは同じくらい簡単であるにもかかわらず、Nimのコードは20倍高速です。アルゴリズムに大きな違いがないと仮定すると、純粋なPythonが純粋なNimの生のパフォーマンスに勝つことは不可能です。なぜなら、Nimのコンパイルプロセスは内部的にCファイルを生成し、それが選択したCコンパイラによってコンパイルされるからです。Nimは標準的なC出力を生成するため、Pythonと互換性があります。 NimからPythonを呼び出す そして PythonからNimを呼び出す。
Nimは経験豊富なPythonユーザーが知識を翻訳するのに便利ですが、より慣用的なコードを書くときに、Nimが独自の言語として輝き始めます(より高速なPythonではなく)。Nimのプログラムは、通常、Pythonのプログラムよりも短く、書きやすいと思います。 他の 素晴らしい 言語 特徴しかし、これらの機能は 1 つの記事の範囲を超えています。私は過去 1 年間、日常的に Nim を定期的に使用しており、そのパフォーマンス、シンプルさ、エレガントさに感銘を受け続けています。次にデータを処理するときには、Nim を試してみてください。CPU が感謝するはずです。
#データ処理に #Python #ではなく #Nim #を使用する理由 #Benjamin #Lee