tag:crieit.net,2005:https://crieit.net/tags/%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C/feed 「電子工作」の記事 - Crieit Crieitでタグ「電子工作」に投稿された最近の記事 2020-01-16T06:22:14+09:00 https://crieit.net/tags/%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C/feed tag:crieit.net,2005:PublicArticle/15684 2020-01-16T06:22:14+09:00 2020-01-16T06:22:14+09:00 https://crieit.net/posts/8bit-CPU-ICF3-Z-Zevios 8bit CPU ICF3-ZのZeviosの除算性能のメモ <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p>8bit CPU ICF3-Zのオリジナルのコア、<a target="_blank" rel="nofollow noopener" href="https://icf3z.idletime.tokyo/download.html">Zevios</a>の除算性能について解説します。Zeviosは2020年1月15日に緩いオープンソースライセンスであるApache License 2.0で公開されました。FPGAに実装できるverilogファイルがあるので、いろいろ性能を測定することができます。</p> <h2 id="Zeviosの除算器について"><a href="#Zevios%E3%81%AE%E9%99%A4%E7%AE%97%E5%99%A8%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">Zeviosの除算器について</a></h2> <p>正しくは除算器というものはなくて8bitの加算器を効率的に動作させることで1サイクルに1bitの商を演算するアーキテクチャです。除算器の性能としては低いのですが、マイコン向けのCPUでは除算器がないものも多く、小さい面積なのに高速に除算ができるものになっています。(除算器としての面積がほとんどない) その除算向けのアーキテクチャを使って8bitより大きい除算をソフトウェアで実装できます。一般の8bit CPUによる実装よりも高速に演算できます。</p> <h2 id="16bit÷8bitの除算"><a href="#16bit%C3%B78bit%E3%81%AE%E9%99%A4%E7%AE%97">16bit÷8bitの除算</a></h2> <p>ICF3-Zでは加算器を使って効率的に演算できるようになっています。17サイクルで演算ができます。</p> <h2 id="24bit÷8bitの除算"><a href="#24bit%C3%B78bit%E3%81%AE%E9%99%A4%E7%AE%97">24bit÷8bitの除算</a></h2> <p>ICF3-Zでは加算器を使って効率的に演算できるようになっています。17サイクルで演算ができます。<br /> ただし被除数の最上位8bitが除数8bitよりも小さい場合に限ります。</p> <h2 id="32bit÷8bitの除算"><a href="#32bit%C3%B78bit%E3%81%AE%E9%99%A4%E7%AE%97">32bit÷8bitの除算</a></h2> <p>16bit÷8bitの除算方法を応用したサンプルコードによる性能は50サイクルです。サンプルコードはgithubで公開されています。<br /> sim2フォルダのpmem.asmzが32bit÷8bitのコードです。</p> <h2 id="32bit÷16bitの除算"><a href="#32bit%C3%B716bit%E3%81%AE%E9%99%A4%E7%AE%97">32bit÷16bitの除算</a></h2> <p>ICF3-Zのアーキテクチャを駆使したサンプルコードによる性能は約350サイクルです。サンプルコードはgithubで公開されています。<br /> sim1フォルダのpmem.asmzが32bit÷16bitのコードです。<br /> ソフトウェアの実装によって性能は違ってくると思われます。もっと高速な方法もあるかもしれません。<br /> 除数が8bit × 8bitの因数に分解できるものなら32bit ÷ 8bitを2回演算したほうが高速です。</p> <p>32bit÷15bitを230サイクルで演算するコードも作ったのですが、まだ十分に検証できていないため、今回は見送りました。</p> <h2 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h2> <p>ICF3-Z Zeviosは、とても少ないトランジスタ数(面積)で実装できるのに高速です。16bit÷8bit、24bit÷8bitの除算が有効につかえるアプリでは低消費電力が期待できるように思われます。</p> spinlock tag:crieit.net,2005:PublicArticle/15676 2020-01-12T04:51:56+09:00 2020-06-03T01:49:25+09:00 https://crieit.net/posts/8bit-CPU-ATmega328 8bit CPU ATmega328の除算性能を測定してみた <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p>ATmega328は Microchipの8bit CPU AVRの1種です。AVRは除算命令がなくArduinoで除算をするコードを書いた場合、どのくらいの性能になるのか測定しました。測定条件でソフトウェア処理が最適化されていないのでAVRのアセンブラを使って最適化をすれば、もっと高速になるはずですが、これはソフト開発環境Arduinoのソフトウエア除算性能の測定です。</p> <h2 id="測定条件"><a href="#%E6%B8%AC%E5%AE%9A%E6%9D%A1%E4%BB%B6">測定条件</a></h2> <p>CPU : ATmega328 クロック 16MHz<br /> ボード: Arduino<br /> ソフト開発環境 : Arduino 1.8.10<br /> 性能を測定する除算 : 16bit ÷ 8bit / 24bit ÷ 8bit</p> <h2 id="測定コード(16bit÷8bit)"><a href="#%E6%B8%AC%E5%AE%9A%E3%82%B3%E3%83%BC%E3%83%89%2816bit%C3%B78bit%29">測定コード(16bit÷8bit)</a></h2> <p>除算を1万回実行して、加算のみの場合との差分を除算1万回の実行時間とします。</p> <pre><code>void setup() { Serial.begin(9600); randomSeed(analogRead(0)); } void loop() { unsigned long s, e, t; unsigned int i; unsigned short x,z; unsigned char y; t = millis(); /* dummy */ s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0xffff); y = random(2,0xff); z += x + y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" time1="); Serial.print(t); Serial.print("\n"); s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0xffff); y = random(2,0xff); z += x / y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" z="); Serial.print(z); Serial.print(" time2="); Serial.print(t); Serial.print("\n\n"); } </code></pre> <h2 id="測定コード(24bit÷8bit)"><a href="#%E6%B8%AC%E5%AE%9A%E3%82%B3%E3%83%BC%E3%83%89%2824bit%C3%B78bit%29">測定コード(24bit÷8bit)</a></h2> <p>除算を1万回実行して、加算のみの場合との差分を除算1万回の実行時間とします。</p> <pre><code>void setup() { Serial.begin(9600); randomSeed(analogRead(0)); } void loop() { unsigned long s, e, t; unsigned int i; unsigned long x,z; unsigned char y; t = millis(); /* dummy */ s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0x7effff); y = random(0x7f,0xff); z += x + y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" time1="); Serial.print(t); Serial.print("\n"); s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0x7effff); y = random(0x7f,0xff); z += x / y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" z="); Serial.print(z); Serial.print(" time2="); Serial.print(t); Serial.print("\n\n"); } </code></pre> <h2 id="結果(16bit÷8bit)"><a href="#%E7%B5%90%E6%9E%9C%2816bit%C3%B78bit%29">結果(16bit÷8bit)</a></h2> <p>除算1万回の実行時間は約128 [mS] 16MHzで動作しているのでサイクル数は2048000 cyc<br /> 除算1回のサイクル数は204.8 cyc<br /> 比較用の加算2サイクルの補正を追加すると<br /> <strong>16bit÷8bit 除算1回のサイクル数は207 cyc</strong></p> <h2 id="結果(24bit÷8bit)"><a href="#%E7%B5%90%E6%9E%9C%2824bit%C3%B78bit%29">結果(24bit÷8bit)</a></h2> <p>除算1万回の実行時間は約373 [mS] 16MHzで動作しているのでサイクル数は5968000 cyc<br /> 除算1回のサイクル数は596.8 cyc<br /> 比較用の加算2サイクルの補正を追加すると<br /> <strong>24bit÷8bit 除算1回のサイクル数は599 cyc</strong><br /> 32bit÷16bitの性能と、ほとんど同じなので、24bit÷8bit用に除算ルーチンを作り直せば性能は向上するのではないだろうか。</p> spinlock