いきなりみどり

数列の平均と標準偏差を算出し,任意の平均および標準偏差の数列へ変換するメソッドを作ろうとしました.元の数列の平均と標準偏差は,処理過程の値として,参照渡しの引数へ突っ込んで返します.

static void f(double* data, int n, double* av, double* sd)
{
	const double AV_DST = 0.0;
	const double SD_DST = 1.0;
	int i;
	double coef, sum, sumSqr;

	sum = sumSqr = 0.0;
	for (i = 0; i < n; i++)
	{
		sum += data[i];
		sumSqr += data[i] * data[i];
	}
	*av = sum / n;
	*sd = (sumSqr - sum * sum / n) / n;

	coef = SD_DST / *sd; // ここ

	for (i = 0; i < n; i++) {
		data[i] = (data[i] - *av)*coef + AV_DST;
	}
}

下から4行目,係数を代入する式を書こうと,「coef=SD_DST/*」まで打った瞬間,以降の文字がいきなり緑になりました.そうか.コメント始まったか.

えんばん

\さいたま/をDVDに焼いてほしいとの依頼を受けました.しかし,自宅にある円盤はDVD-RAMだけ.読めないDVDプレーヤー,多い気がします.そーいや個人では滅多に使わないからと,DVD-Rは会社へ持っていった気がします.

デスクの引き出しに,スピンドルケースに入った約20枚の円盤が眠っていました.鞄に突っ込んで帰宅.

開けてびっくり玉手箱.記録面が青くない.薄緑.これDVD-Rちゃう,CD-Rやんか.そーいや,個人では滅多に使わないという理由に加え,数MB程度のファイルの納品に4.7GBのDVD-Rを使うのが勿体ないという理由もあって,の私用円盤供出でした.骨折り損の草臥れ儲け.プラスチックの塊,また会社へ.

てぬき

今朝書いた昨日分の日記,調べ物など気合入れたご褒美に,今日の分は手抜きします.家の別のPCのスペックも比較表にしてみようかと.新しいOSに対応していないプリンタで印刷するのと,録り溜めアニメをDVD-RAM経由でリッピングするため,だけに使っているPCです.苦手な調べ物をわざわざしたため,労力的には手抜きになりませんでした.結局,対応する項目が調べきれていませんが,下表な感じ.

自宅Desktop新自宅Desktop旧
CPU名Celeron G3900Celeron E1400
発売年2015年2008年
コア数2コア/2スレッド2コア/2スレッド
基底周波数2.8GHz2.0GHz
キャッシュ容量2MB512KB
RAM容量4GB2GB
OSWindows10WindowsVista

ひかくひょうすきです

先日,自宅DesktopPCでのテレワークで,のろのろ運転を体験しました.計画テレワークの際は,会社LaptopPCを持ち帰るようにしています.そのPCでは,あたかも会社DesktopPCで作業しているかのように,さくさく運転です.

将来の自宅PC買い替えの参考のため,この速度違いが何に由来するのか,調べてみようと思いました.ガンガンにHDDアクセスしている風ではないので,HDDの回転数はあまり関係ない気がします.複数アプリの同時起動を嫌っているので,RAMもあまり関係ない気がします.実際タスクマネージャを見ても逼迫していない感じですし,常駐サービスはむしろ会社PCの方が多くて重そうです.となると,やはりCPUが鍵なんでしょう.

学生時代は,周波数が処理速度とほぼ相関するものと思っていました.ところがもはや周波数競争は飽和し,やがてはコア数競争になった感じ.でも,周波数とコア数以外にも,性能に帰する要素はたくさんあるでしょう.

自宅Desktop会社Desktop会社Laptop
CPU名Celeron G3900Core i7-3770Core i7-7500U
Intel世代第6世代Skylake第3世代Ivy Lake第7世代Kaby Lake
発売年2015年2012年2016年
希望小売価格4,600円31,700円43,100円
コア数2コア/2スレッド4コア/8スレッド2コア/4スレッド
基底周波数2.8GHz3.4GHz2.7GHz
キャッシュ容量2MB8MB4MB
バス転送速度8GT/s5GT/s4GT/s
RAM容量4GB8GB8GB
OSWindows10Windows8Windows10

というわけで,その辺を調べてまとめました.比較表好きです.実効的な処理性能としては,「自宅Desktop<会社Desktop≒会社Laptop」という感じです.

この方程式と上表を対応付けると,RAM容量,やっぱり関係あるのかしら.ま,RAM が逼迫しないよう遅いHDDでページングし,その上での使用率をタスクマネージャに表示している,ってこともあるでしょうからね.

あとはIntelの世代かしら.ここ違うと結構性能差ありそう.とかいろいろ思いましたが,結局そもそもの話,廉価指向のCeleron/性能指向のCore i7の違いが最大要因でしょう.もはや土俵が違うレベルか.

あうゑいと

C#で非同期メソッドを呼び出す際に使うawaitステートメント,この挙動を誤解していました.非同期処理を同期的な順で処理しつつ元スレッドを専有しない便利なやつ,という認識でしたが,ちょっと違うぽ.私が誤解していたawaitの挙動は以下のとおりでした.

  1. 別スレッドでタスクを開始する.
  2. 元スレッドは一旦解放される.(だから元スレッドでの他のタスクが動かせる)
  3. 別スレッドでの処理が終わったら,元スレッドでawaitの続きを処理する.

正しいawaitの挙動は以下のとおりだったようです.

  1. 別スレッドでタスクを開始する.
  2. 元スレッドは一旦そこでメソッドを抜ける.(だから呼出元の続きの処理が並行で消化される)
  3. 別スレッドでの処理が終わったら,元スレッドでメソッド内のawaitの続きを処理する.

大抵,非同期メソッドをawaitで呼ぶ非同期メソッドは,それ自体もawaitで呼ばれます.この場合の挙動は正解と誤解に差がないため,今まで気づけないでいました.

自戒を込め,気合い入れて例示してみます.まず,普通の例.ま,こうなるよね.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task _ = MethodA();
        }

        static async Task MethodA()
        {
            Console.WriteLine("MethodA started.");
            await MethodB();
            Console.WriteLine("MethodA finished.");
        }

        static async Task MethodB()
        {
            Console.WriteLine("MethodB started.");
            await Task.Run(() =>
            {
                Console.WriteLine("Run started.");
                Thread.Sleep(3000); // HeavyTask
                Console.WriteLine("Run finished.");
            });
            Console.WriteLine("MethodB finished.");
        }
    }
}
実行結果:
MethodA started.
MethodB started.
Run started.
(ここで3秒待ち)
Run finished.
MethodB finished.
MethodA finished.

そして,これが私の理解と違った例.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task _ = MethodA();
        }

        static async Task MethodA()
        {
            Console.WriteLine("MethodA started.");
            Task _ = MethodB(); // <-------- ここを変えた
            Console.WriteLine("MethodA finished.");
        }

        static async Task MethodB()
        {
            Console.WriteLine("MethodB started.");
            await Task.Run(() =>
            {
                Console.WriteLine("Run started.");
                Thread.Sleep(3000); // HeavyTask
                Console.WriteLine("Run finished.");
            });
            Console.WriteLine("MethodB finished.");
        }
    }
}
実行結果:
MethodA started.
MethodB started.
MethodA finished.
Run started.
(ここで3秒待ち)
Run finished.
MethodB finished.

誤解していた私は,「普通の例」との違いが「MethodBの処理中に元スレッドで他のタスクが動かせるかどうか」だけで,ゆえに同じ実行結果になると思っていました.つまり,思っていた動きは以下のとおりです.

  1. MethodA started.
  2. 元スレッドでMethodB started.
  3. 別スレッドで3秒かかる処理.元スレッドは別スレッドの処理完了待ち.
  4. 3秒後,元スレッドでMethodB finished.
  5. 呼出元のMethodA finished.

で,正しい動きはなるほど,以下のとおりとなるわけです.

  1. MethodA started.
  2. 元スレッドでMethodB started.
  3. 別スレッドで3秒かかる処理開始.元スレッドはMethodBを抜けて(中断して)呼出元の続きのMedhodA finished.
  4. 3秒後,元スレッドでMethodB finished.

すぴる

自宅のPCのOffice365のExcelがいつの間にか更新されていました.「スピル」って何? ググりました.配列形式が返ってくる関数に関するものらしいです.

従来は,埋め先の複数セルを選び,Ctrl+Shift+Enterを押すことで,計算結果を複数セルへ出していました.ところが,新しいExcelでは,そんなことしなくても,起点のセルに数式を入れることで,隣接セルが動的に変わるらしいです.これはまあ便利.

でも,逆に隣接セルを変えたくない場合はどうしたら良いのか.その場合は数式の前に「@」を付けるらしいです.こうすると従来同様,入力したセルにしか値が入らなくなります.なるほど.

専らExcel使いですし,毎年新人研修でExcel等を教える係になっているので,この辺は一応押さえておきたいところ.

まてる

朝から客先直行.乗れない電車を警戒し,少し早めに出ました.そして早めに着きました.待つ間,メールやビジネスチャットをチェック.そーいや1箇月前,のっけから200kbpsで行く通信プランに変えました.たしかに,明らかにメール等の表示が遅くなりました.でも,この程度なら待てます.ありです.急いでいるときは苛々しますが,そのときは速いプランでも同様でしょう.

むずかしくないはずなのに

カメラのライブラリを呼び出し,画像を一コマ一コマ順次取得し,フロントアプリへ投げ,動画のように表示させるためのライブラリを作っています.似たようなのを何度も作ったことがあるのに,いや,あるがゆえに簡単にできそうだと思っているためにか,なかなかうまく行かずに嫌になっちゃう.

カメラのライブラリはC言語で呼び出します.一方,表示アプリはC#/WPFです.そのため,繋ぎの自作ライブラリはC++/CLIで作っています.開始メソッドを呼んだら,画像の取得と転送を別スレッドで行います.C言語寄りのところでは関数ポインタが登場し,C#寄りのところではデリゲートが登場します.C言語寄りのところでは画像情報をmallocしたアンマネージドなunsigned char*型で保持したりしますが,C#寄りのところではマネージドなarray<unsigned char>^型で保持したりします.速度面ではなるべくアンマネージドが良いけど,mallocとfreeをちゃんとやらないとメモリリークするとか,CLIだとstd::threadが使えないなど,いろいろあります.

の,どこまでをどっち流に書くか,プログラムの構成含めてトライアルアンドエラーでスクラップアンドビルドでした.さらに,C言語とC++とC++/CLIとC#を,それぞれちゃんと理解していないと,たちまち書き間違えて怒られる罠.テトリスだわ.

やってみんとなんもいえんやろ

楽天モバイルです.通話SIMです.高速通信できる1箇月当たりのデータ量として,上限0GB,3.1GB,5GB,10GB,30GBが選べます.超えると200kbpsのベストエフォートになるようです.そもそも超えない場合の高速はどんだけなのか,調べても見つけられませんでしたが,以前調べたときは260Mbpsでした.こりゃだいぶ違いますね.

引越前は自宅からインターネットへ行く際,テザリングしてました.だから5GBのプランにしていました.引越後は壁までインターネットが来ているので,全くテザリングしなくなりました.3.1GBのプランにしていましたが,毎月0.6GBくらいしか使わないの.もったいない.でも,その下だと初っ端から低速になっちゃう.さて,どうしたものか.

学生時代,32kbpsの通信速度を体感した身です.と言って18年前の日記にリンクを張ってみる.たしか,「月25時間まで定額,以降従量課金の64kbps」のコースから「無制限32kbps」のコースへ変えたんでした.祖父母の持ち家住まい@拡大家族だったので,電話回線を分配するなど,設備にメスを入れる系はできませんでした.で,Windows98SEのノートPCにCF型のカードを差して実現していました.懐かしい.

当時,画像表示をOFFにした状態でネットを泳いでいましたが,それでも32kbpsはだいぶノロノロだった印象です.で,200kbpsはいかほどのものかと.約6倍になっているとはいえ,現代は諸々がブロードバンド前提のつくりになっているのではないかと.そんなところをナローバンドで太刀打ちできるのかと.なんやかんや出先でメールやらビジネスチャットやらを覘いたりするぜ.支障あるんとちゃいますか.

という思いでこれまで,保守派の私はギガを捨てていました.うーん,でもこのままだともやもやしたままずるずるだなと.思い切って0GBのプランにしてみました.月額1600円が1250円になります.22%OFFです.様子見するぜ.

ぱすもかすいか

交通系ICカード型の定期券を改札にタッチすると,有効期限が迫っている場合,その期日が「〇月〇日」と表示されます.先日,私の前の人が通り抜けた際,「〇.Dec.」と表示されていました.見ると,外の人でした.もしかして,購入時に操作中の言語の設定が登録され,改札通過時の表示に反映されたりしているんでしょうか.いつも使い慣れているシステムの知らない一面を見た感じです.