新しい VC++ のコンパイラを試す
ツイッターを見てたら、
Introducing a new, advanced Visual C++ code optimizer | Visual C++ Team Blog
こんなのがありまして、へー、でも試すの面倒くさいなぁと思っていたらですね、
こんなのもあって、要は、「nuget で簡単に最新コンパイラ試せるよ!」ってなってたわけです。
知りませんでした。簡単ですねー。
で、
ってあったんですが、コマンドラインから叩きたい。既に VS2015 入っているという僕には、いろいろ面倒そうなので、別の未知を模索してみました。
インストールしてみた(自己流)
とはいえ、やったことは簡単です。
http://dist.nuget.org/win-x86-commandline/latest/nuget.exe
をダウンロードして、適当なフォルダに配置して、
nuget install VisualCppTools -source http://vcppdogfooding.azurewebsites.net/nuget/ -Prerelease
って実行しました。そうすると、 VisualCppTools.14.0.24104-Pre\lib\native に dll やら exe やらが沢山展開される。
このまま実行しても良いですけど、 CRT のヘッダ・ライブラリしかないよんって感じなので、どうにか Windows 系のヘッダとかも参照したい。
しばらく考えた末、
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" set PATH=C:\Users\kawasaki\Desktop\cl\VisualCppTools.14.0.24104-Pre\lib\native\bin\amd64;%PATH%
続続) 気づいたら、C# が C++ の速度を凌駕している!
先日の記事、
.NET Native だとどうよ?っていう話があったので、試してみました。
コードは趣旨を変更しない範囲で弄りました。
スレッドプールのプライオリティとかどうなってんの?っていう疑問はあるんですが、
実行した感じ、それらの影響はなさそうなので、結構適当です。
概要だけ提示できれば良いので、XAMLは提示しませんが、普通にバインドして表示しているだけです。
using System; using System.Collections.ObjectModel; using System.Diagnostics; using System.Threading.Tasks; using Windows.UI.Xaml.Controls; namespace App1 { public sealed partial class MainPage : Page { public ObservableCollection<double> Times { get; } = new ObservableCollection<double>(); public MainPage() { this.DataContext = this; this.InitializeComponent(); Loaded += (s, e) => workOnBackground(); } async Task workOnBackground() { double t1 = 0, t2 = 0; await Task.Factory.StartNew(() => { int w = 4321; int h = 6789; int stride = (w + 3) & ~3; var a = new byte[stride * h]; t1 = time(() => test1(a, w, h, stride)); t2 = time(() => test2(a, w, h, stride)); }); Times.Add(t1); Times.Add(t2); } static void test1(byte[] a, int w, int h, int stride) { for (int y = 0; y < h; y++) { int offset = y * stride; for (int x = 0; x < w; x++) { a[x + offset] = (byte)(x ^ y); } } } static unsafe void test2(byte[] a, int w, int h, int stride) { fixed (byte* p0 = a) { for (int y = 0; y < h; y++) { byte* p = p0 + y * stride; for (int x = 0; x < w; x++) { p[x] = (byte)(x ^ y); } } } } static long time(Action action, int count = 100) { var tw = new Stopwatch(); tw.Start(); for (int i = 0; i < count; i++) action(); tw.Stop(); return tw.ElapsedMilliseconds; } } }
結果
32-bit/64-bit で特に何の差も見れませんでしたので、そこに関しては割愛。
結局、ここにある、 "Compile with .NET Native tool chain" を ON/OFF した結果だけです。
OFF の時。
ON の時。
面白いですねー。
.NET Native が OFF の場合の速度の傾向はフルの .NET Framework 4.6 のコードと同じですね。配列は遅く、 unsafe は速い。ただ、前回調べた、 .NET Framework 4.6 や C++ と比べると、微妙に遅いですね。
ところが、 .NET Native を ON にすると、配列と unsafe の速度差がグッと縮む。速度的に、2~3%程度の差しかありません。この差だと、 unsafe コードを無理して使わないでも良いような気がする速度です。
この差を見せられると、時間をかけてコンパイルできる AOT コンパイラは馬鹿に出来ないなぁと思わざるを得ません。
.NET Framework 4.6 や C++ との速度差は、プライオリティの問題かもしれませんし、フレームワーク自体の問題かもしれませんし、その他のノイズかもしれません。調べるのが面倒なのでそこまでは追求しません。
続) 気づいたら、C# が C++ の速度を凌駕している!
先日のこの記事ですが、
メモリ確保を関数の中でやってるのが悪いんじゃね?疑惑がありまして、そうなのであれば・・・ということで書き直しました。モダンな感じで。
C# 版
// Compile: csc /o /unsafe speedtest.cs using System; using System.Diagnostics; class SpeedTest { static void test1(byte[] a, int w, int h, int stride) { for (int y = 0; y < h; y++) { int offset = y * stride; for (int x = 0; x < w; x++) { a[x + offset] = (byte)(x ^ y); } } } static unsafe void test2(byte[] a, int w, int h, int stride) { fixed (byte* p0 = a) { for (int y = 0; y < h; y++) { byte* p = p0 + y * stride; for (int x = 0; x < w; x++) { p[x] = (byte)(x ^ y); } } } } static void time(Action action, int count = 100) { var tw = new Stopwatch(); tw.Start(); for (int i = 0; i < count; i++) action(); tw.Stop(); Console.WriteLine(tw.ElapsedMilliseconds); } static void Main(string[] args) { int w = 4321; int h = 6789; int stride = (w + 3) & ~3; var a = new byte[stride * h]; time(() => test1(a, w, h, stride)); time(() => test2(a, w, h, stride)); } }
C++ 版
// Compile: cl /MD /Ox /EHsc speedtest.cpp #include <stdio.h> #include <windows.h> #include <functional> typedef unsigned char byte; static void test2(byte* a, int w, int h, int stride) { auto p0 = a; for (int y = 0; y < h; y++) { auto p = p0 + y * stride; for (int x = 0; x < w; x++) { p[x] = (byte)(x ^ y); } } } void time(std::function<void()> action, int count = 100) { auto start = GetTickCount(); for (int i = 0; i < count; i++) action(); printf("%u\n", GetTickCount() - start); } int main() { int w = 4321; int stride = (w + 3) & ~3; int h = 6789; auto a = new byte[stride * h]; time([=]() { test2(a, w, h, stride); }); delete[] a; }
気づいたら、C# が C++ の速度を凌駕している!
5年半程前に書いた、この記事。
C#というか、.NET Framework 4.6 は、 RyuJIT という新しい JIT の導入によって、64-bit 環境での実行が高速化されています。なので、さーて、少しは面白い結果が出るんじゃないかなぁーと。
で、環境は、
Windows 10 Pro Insider Preview Build 14332
.NET Framework 4.6.1
Visual Studio 2015 Update 2
CPU: Intel Core i7-3770S 3.1GHz
Memory: 32GB
という環境です。ここで、実行してみました。
まずは、C#版。
3091
2282
上が配列。下が unsafe コード。unsafe が速くなってます。74%ぐらいの時間で終わるようになってる。
unsafe コードを書くモチベーションが上がります。better C として考えると、モチベーション上がりますねー!
さて、C++版。
2344
んん?あれっ?実行するプログラム間違った?
いや、間違ってない。
遅いじゃないですかー。C#に負けてるじゃないですかー。これ、64-bit 版です。
32-bit だったら?
2343
変わんねー。
C++ 敗北。
もう、C++使う理由がなくなる感じなのでは・・・。
仕事によっては、C++指定、あるいは、そうせざるを得ないことってありますけど、この結果は予想外です。個人的には、嬉しいです。
mac mini (Late 2014) の HDD を SSD に換装した
mac mini で作業をしているんですが、アプリの起動に10秒以上かかったり、brew install XXX とかすると数十分戻ってこなかったり、ウンザリしていました。まぁ、買うときにサブマシンという理由でお金をケチって HDD モデルにしちゃったのが問題なのですが、 SSD にしたら速くなるんじゃね?っていう予想に基づいて、 SSD への換装を行うことにしました。
最初にやっておくこと
クリーンインストールする気なら、この作業をする前に、OSのインストール USB を作っておきましょう。
- AppStore で El Capitan とかをダウンロードしておきます。結構デカいので、時間がかかるかも知れません。
- createinstallmedia で USB に起動ディスクを作成する
割と面倒なので、分からない人は他のサイトをググってください。
support.apple.com
必要な工具
- TR6/T6 トルクスドライバー
肝心のドライバー。ネジが全部、所謂、トルクスネジ(Torx Screw)って奴になっていて、これに合うドライバーが必要なんですが、Amazonでググっても、 TR6 Torx とかはなかなか出てきません。なので、結論から書くと、
www.amazon.co.jp
これを買えば、全部OKです。Fixit にある、 T6、あるいは、TR6 は全て、このドライバーでは、 T6 が使えます。というか、 HDD を固定しているネジ以外は、全部、これだけで OK です。HDD は、T7 ですが、それも付属しているので、本当にこれだけ買えば分解に困る事はありません。
- 柔らかいヘラ的
後は、裏蓋を開けるのに、柔らかいヘラ的なものが必要ですが、僕は、手元の接着剤に付属していたプラスチック製のヘラを使いました。
作業
まぁ、下の奴を見てくださいな。っていうのでほとんど終わっちゃうんですけど。
ただ、ネジの数多いし、意外と面倒な部分が沢山あります。
まぁ、後は、英語が読めないとすぐには理解できなさそうなのは、ACのプラグ部分を反時計回りに90度回せっていう部分(先にその部分を固定している金属製のピンを抜く)とかぐらいかな?
そして、ロジックボードを引っ張り出す部分とかは、
みたいな感じで、適当な硬い棒があればそれでどうにかなるでしょう。
ちなみに、僕が買った SSD は、 SAMSUNG の 850 EVO 500GB。コスパはおそらく最強レベルではないかと。
そして、こちらが僕を苦しめた激遅 HDD。5400rpm ってこんなに遅かったんでしたっけ?
あと、 HDD をはずそうとしているときに、一瞬、間違って、この蓋のネジをはずそうとしてしまいました。これも、なにげに T6 トルクスネジなんですよね。