2013年12月9日月曜日

続 C# は高級アセンブラ

C# は高級アセンブラの続きです。
何とかして高速化しようと思い試してみました。まずはボツ案から。
あ、はい、ごめんなさい。


時計屋さんからこのようなヒントを頂きました。
これを元にソート方法を見直し…というよりソート行為がほぼ不要になったためについでにzero copyも取り入れたところ、逆にコードがキレイになってしまいました。 スコアも上々で、0.02 / 0.02 / 0.03となりました。
更に続きを書きました。続続 C は高級アセンブラ

2013年12月6日金曜日

C# は高級アセンブラ

タイトルに意味はありません。
今、新人女子プログラマの書いたコードを直すだけの簡単なお仕事です!|というオンラインハッカソンがアツいです。特に野田さんのニーソは素晴らしいです。
私はC#言語しか使えないので頑張って書いてみました。採点結果は0.02秒 / 0.02秒 / 0.05秒の100点になりました。これが私の限界のようなのでgistにソースコードを公開しておこうかと思います。
特筆することはない至極素直なコーディングに心がけましたが…ちょっとだけ解説を。

  • Array.Sort()はネイティブコードで実行されるので速いはずですが、Monoの場合マネージコードで実行されます。
  • Array.BinarySearch()とMonoのArray.Sort()はComparisonやIComparerで比較されますが、これは組み込みの比較演算子に比べて遅いです。
  • もっと言うとIEnumrableは組み込み配列に比べて遅いです。
  • stringインスタンス生成にはUnicodeへの変換などが絡むため遅いです。
  • そもそもI/Oは遅いので呼び出し回数は可能な限り削減しましょう。
  • MSILには4引数、4変数までは個別にオペコードが用意されていますが、それ以上の引数・変数に対してはオペランドでインデックス指定するため1バイトずつ長くなります。結局JITでネイティブのレジスタアクセスに変換されるので、気のせいといえば気のせいですが。
こんなところでしょうか。

さらにブレイクスルーがあったので続きを書きました。

2013年8月25日日曜日

F#の%a書式指定はとても扱いづらい

F#のPrintfモジュールはある程度の書式指定ができるようになっていますが、基になっているOCamlが貧弱なせいもあってString.Format()ほどの表現力はありません。 何か手はないかと考えたところ %a 書式指定を思い出しました。Core.Printf モジュールには

2 つの引数を必要とする一般的な書式指定子。 1 つ目の引数は、2 つの引数を受け取る関数です。この関数の 1 つ目の引数は、指定した書式設定関数 (TextWriter など) に対応する型のコンテキスト パラメーターです。2 つ目の引数は出力する値であり、この値によって、該当するテキストを出力するか、返すかを指定します。
2 つ目の引数は、出力する特定の値です。

とあります。いまいちわかりづらいので英語版ドキュメントも確認しましたが同じ内容で意味がよくわかりません。念のためOCamlのmodule Printfも確認します。

user-defined printer. Take two arguments and apply the first one to outchan (the current output channel) and to the second argument. The first argument must therefore have type out_channel -> 'b -> unit and the second 'b. The output produced by the function is inserted in the output of fprintf at the current point.

なるほどわかりません。

とりあえずF#で書いてみたところ、非常に面倒くさいことが判明しました。1つ目の引数の説明「TextWriter など」が罠です。 なんとprintfとsprintfとで要求される関数が違いました。具体的に関数を挙げた方がわかりやすいので、現在時刻をコンソール出力してみます。

let formatter_for_printf (textWriter : TextWriter) (dateTime : DateTime) = textWriter.Write("{0:MM/dd HH:mm}", dateTime) let formatter_for_sprintf () (dateTime : DateTime) = String.Format("{0:MM/dd HH:mm}", dateTime) printfn "%a" formatter_for_printf DateTime.Now sprintf "%a" formatter_for_sprintf DateTime.Now |> Console.WriteLine

つまり同じ %a でも

  • printfで出力する時は(TextWriter -> 'T -> unit) 'Tが必要
  • sprintfで出力する時は(unit -> 'T -> string) 'Tが必要

ということのようです。

OCaml側は確認していませんがドキュメントからはそう読み取れないため、F#の(限りなくバグに近い)仕様かなと思います。

2013年5月29日水曜日

DataContractJsonSerializerでDictionaryを表現 再び

以前、DataContractJsonSerializerでDictionaryを表現という記事を書きましたが、あれから4年半経ち時代が変わりました。 .NET Framework 4.5からDataContractJsonSerializer constructorDataContractJsonSerializerSettings classを引数に取り、このclassはUseSimpleDictionaryFormat propertyを持っています。 そう、つまり…標準機能でDictionaryが表現できるようになっていました。

2013年2月16日土曜日

F#の||>演算子について

F#言語仕様には|>演算子と||>演算子と|||>演算子が定義されています。|>演算子はシンボルと演算子のリファレンスにも掲載されていますし、比較的よく使われています。

x |> f
とすると f(x)が実行されるものです。さて残りの2つ、これらは言語仕様には存在だけが記されており、それぞれop_PipeRight2、opPipeRight3にコンパイルされることしかわかりません。調べたところ、これらは
let inline (|>) x f = f x let inline (||>) (x,y) f = f x y let inline (|||>) (x,y,z) f = f x y z
のようなものだということがわかりました。つまり左辺にはタプルを受け、右辺の関数にタプルの値を展開して引数として適用するものです。

結論。高度に発達した関数型言語はググラビリティが非常に高い。(op_PipeRight2でググったけどこの話題が全然見つからなかった…。)

2012年12月10日月曜日

-ms-filterは無意味

Microsoft Internet Explorerにはバージョン4.0で導入されたfilterプロパティがあります。IEバージョン8からCSS標準に準拠するために-ms-filterプロパティが導入されました。しかし導入経緯を理解せず、ただ単に記述しているサイトおよび解説サイトを散見するため、この記事を書きました。

2012年6月4日月曜日

CSS Media Queries Hacks

​スタイルシートは認識するセレクター・プロパティにだけ適用されればそれで済むはずと考えていたこともありました。しかし、CSS animationのできるブラウザーではCSS Sprite画像を読み込んだ上でアニメーション、そうでないブラウザーではアニメーションGIF画像を読み込む、なんてことをする場合、どちらのブラウザーでもbackground-imageプロパティは認識されてしまうため、ブラウザーに応じて動作を変えることができません。

そこで目を付けたのがCSS Media Queriesという機能です。この機能を使うとブラウザーのサイズなどに応じてスタイルシートを変更することができます。
各種ブラウザーには独自の拡張機能がありこれを利用するとブラウザーごとに異なるスタイルを適用することができます。昔あったスターハックの合法版といったところでしょうか。

これを組み合わせるとこんな風に書けます。
@media (-moz-touch-enabled:0), (-moz-touch-enabled:1){ /* Gecko 1.9.2 (Firefox 3.6)以降に適用 */ } @media (-moz-device-pixel-ratio){ /* Gecko 2.0 (Firefox 4)以降に適用 */ } @media (-ms-high-contrast: none){ /* Internet Explorer 10に適用 */ } @media (-webkit-animation){ /* Webkit (Safari4以降 or Chrome)に適用 */ }
簡単ですが動作サンプルを。