資料」カテゴリーアーカイブ

x264でエンコード中にFPSが低下する

動画をx264で変換中、後半になるとFPSが急激に下がる現象が発生したので原因を探りました。
結論から書くとCPUの温度が高温になったためでした。

以下、調べた内容をまとめて記録

タスクマネージャーの「パフォーマンス」タブのリソースモニターにて

  • CPU使用率は高い
  • メモリはまだ空きがある
  • ディスクI/Oは余裕がある

この段階で、ボトルネックになっているのがCPUだと推測

改めてリソースモニターのCPUの欄を見ると「最大周波数」の欄が「33%」になっている。
つまり、そもそもCPUの動作速度が引き下げられいる。
「じゃ、理由は?」ってことで以下の2つ考えた

  • 省エネモードが作動してCPUの動作速度を落としている
  • 熱によりCPUが破損するのを防ぐためCPUの動作速度を落としている

2つとも、存在する機能らしいってぐらいは知識としあるけれど実際しらないのと等しいので調べてみた。
(使用していたCPUはintel Core 2 Quad Q6600なのでintel CPUの内容となります。)

CPUの省エネ機能

  • C1Eステート
    CPUを休止状態にする機能。
    CPUは何もタスクを実行していない場合、消費電力を抑えた状態に移行し、CPUの動作クロックも一定の値まで下げられる
  • EIST(Enhanced Intel SpeedStep Technology)
    CPUの消費電力を抑える技術。
    CPUの使用状況にあわせて動作周波数と駆動電圧を落として消費電力を低減する。

CPUの熱からの保護機能

  • Thermal Monitor
    CPUを熱による破損から守る保護機能。
    TM1では異常時に周波数のみ、TM2では周波数と電圧を下げ、CPUの処理量を減らすことでCPUの発熱量を減らす。
    (サーマル・スロットリングと呼ばれることもあるようだが資料が見つからない・・・)

上記の事から今回の挙動がTM2の発動によると考え、CPU温度を見てみることに。
使用するソフトは「Core Temp」が無料で使用できる。
(standaloneとLanguage packをダウンロードした場合はCore Tempフォルダ内にLanguagesフォルダを作成し、言語ファイルを格納する)

見てみると95℃を超えておりたまに100℃に達している状况だった早急にPCケースのサイドパネルを外し、扇風機の風をCPUに対して、45°の角度で風を当てた。(垂直に当てるとCPUクーラーに負荷がかかると考えてこうしたけど、どうすれば一番いいのか知らないです。)
すると、温度が75℃付近になるとFPSも回復が見られたので、今回のFPSの原因はCPU温度で有ることが確認できた。

そもそも、CPUの適正温度ってどれくらいなのだろう
複数のサイトを見た感じ以下の温度が目安のようだ。

  • 40〜60℃:通常時
  • 60〜75℃:高負荷時

今回この現象が発生したPCのCPU Core 2 Quad Q6600はTM2は大体95℃ぐらいで働いた。
このあたりはもしかするとBIOSで設定できるのかも知れないが確認していない。

[C#]アプリケーションのUAC対応

アプリケーション側で一般権限と管理者権限とで挙動を変えたい場合のメモ

  1. WindowsVista以降(UAC搭載OS)で起動されているか
    アプリケーションがWindowsVista以降で起動されているかどうかをOSのバージョン情報から判断する 

    using System;
    
    private bool IsUAC()
    {
        OperatingSystem osInfo = Environment.OSVersion;
        if (osInfo.Platform == PlatformID.Win32NT)
        {
            if (osInfo.Version.Major == 6)
            {
                if (osInfo.Version.Minor == 0)
                {
                    // Windows Vista, Windows Server 2008
                    return true;
                }
                else if (osInfo.Version.Minor == 1)
                {
                    // Windows 7, Windows Server 2008 R2
                    return true;
                }
            }
            else if (osInfo.Version.Major > 6)
            {
                // new Windows
                return true;
            }
        }
    
        return false;
    }
    
  2. アプリケーションが管理者権限で起動されているか
    アプリケーションが「管理者として実行…」されているとき 

    using System.Security.Principal;
    
    private bool IsAdministrator()
    {
        bool isAllowed = false;
    
        try
        {
            WindowsIdentity wi = WindowsIdentity.GetCurrent();
            WindowsPrincipal wp = new WindowsPrincipal(wi);
            isAllowed = wp.IsInRole(WindowsBuiltInRole.Administrator);
        }
        catch
        {
            isAllowed = false;
        }
    
        return isAllowed;
    }
    
  3. アプリケーションを起動したユーザーはAdministratorsグループに属しているか
    アプリケーションは一般権限で起動されていたとしても起動したユーザーが管理者に昇格可能かどうか知りたいとき 

    using System.DirectoryServices.AccountManagement;
    
    private bool IsAdministrators()
    {
        bool isAllowed = false;
    
        try
        {
            PrincipalContext pc = new PrincipalContext(ContextType.Machine, null);
            UserPrincipal up = UserPrincipal.Current;
            GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "Administrators");
            if (up.IsMemberOf(gp))
            {
                isAllowed = true;
            }
        }
        catch
        {
            isAllowed = false;
        }
    
        return isAllowed;
    }
    

    上のコードだといくつかの環境でうまく動いていないっぽい?下のコードのほうが確実かも。

    using System.DirectoryServices.AccountManagement;
    
    private bool IsAdministrators()
    {
        bool isAllowed = false;
    
        try
        {
            PrincipalContext pc = new PrincipalContext(ContextType.Machine, null);
            UserPrincipal up = UserPrincipal.Current;
            foreach (GroupPrincipal gp in up.GetGroups())
            {
                try
                {
                    if (gp.Name.ToLower().Equals("Administrators".ToLower()))
                    {
                        isAllowed = true;
                    }
                }
                finally
                {
                    gp.Dispose();
                }
            } 
        }
        catch
        {
            isAllowed = false;
        }
    
        return isAllowed;
    }
    
  4. アプリケーションを管理者権限で再起動する
    処理を行う際に管理権限が必要となった場合に自分自身を管理者権限で再起動する 

    using System;
    using System.Diagnostics;
    
    private void RestartApplication()
    {
        ProcessStartInfo psi = new ProcessStartInfo();
        psi.UseShellExecute = true;
        psi.WorkingDirectory = Environment.CurrentDirectory;
        psi.FileName = Application.ExecutablePath;
        psi.Verb = "runas";
    
        try
        {
            Process p = Process.Start(psi);
        }
        catch
        {
            return;
        }
    
        Application.Exit();
    }
    
  5. 管理者権限が必要になるボタンにUAC(盾)のアイコンを表示する
    操作の続行に管理者権限が必要になることをユーザーに知らせるためボタンにUAC(盾)のアイコンを表示する
    (SystemIcons.Shieldプロパティの盾アイコンとWin32APIの盾アイコンには差があり、Windows 7で標準的に使われているのはWin32 APIのほうである。) 

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace Sample
    {
        public partial class Form1 : Form
        {
            [DllImport("user32.dll")]
            private static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    
            // 第2パラメータ:盾アイコンを設定するフラグ
            uint BCM_SETSHIELD = 0x0000160C;
    
            public Form1()
            {
                InitializeComponent();
    
                // ボタンの外観を「System」にする必要がある
                button1.FlatStyle = FlatStyle.System;
            }
    
            private void checkBox1_CheckedChanged(object sender, EventArgs e)
            {
                // 第1パラメータ:ボタンのウィンドウ・ハンドル
                HandleRef hwnd = new HandleRef(button1, button1.Handle);
    
                if (checkBox1.Checked)
                {
                    SendMessage(hwnd, BCM_SETSHIELD, new IntPtr(0), new IntPtr(1));
                }
                else
                {
                    SendMessage(hwnd, BCM_SETSHIELD, new IntPtr(0), new IntPtr(0));
                }
            }
        }
    }
    

PSPのバックライトヒューズの交換

PSPのバックライトヒューズの位置
PSP-1000の画面が突如表示されなくなった。
音は聞こえるし、ボタンも効いてる音がする。

目を凝らしてみると、薄ーく表示はされていた。

この状況からバックライトが切れたとの推測をしてネットで情報を調べると
さすが先駆者がいらっしゃる。

丁寧にバックライトのヒューズの位置まで公開してくれていたので
早速、分解し、ヒューズの導通を確認してみる。

デジタルマルチメーターでは反応なしだが、ヒューズ自体は1005サイズのチップヒューズで
そもそもちゃんと測れているのか分からなかった。
例えば、表面に薄い膜とかあったら測れないだろうし。

駄目元で交換してみることにした。
交換対象はF4501の0.5Aのヒューズ。
まず、方針として交換することを考えていたけれど半田が思うように溶けず断念。
そこで、並列につけることにした。
これなら、厳密にはこれもよろしくないのだが(既存のヒューズが生きていた場合、電流が分割されるため)、
この作業でバックライトが復旧したなら、ヒューズは切れているものと考えられるし、
駄目なら別に原因があるものとして、外せばいいので。

で、作業を行ったところ無事バックライトが復旧。
再びPSPで遊べるようになった。

玄箱の電源修理

玄箱の電源回路のヒューズリード付きヒューズ
玄箱の電源プラグを差したまま、誤って電源に触れてしまい、ヒューズを切ってしまったのでその修理作業をメモ

玄箱は初代の無印のもの。
電源プラグを抜いたつもりだったけれど実際に抜いたのは別の電源プラグで、玄箱の電源は抜けていなかった。
抜けているものとして作業をしたために電源のヒューズと抵抗の足に触れてしまい青い火花が散った。

しびれる手には目もくれず慌てて、故障してないか確認するために電源を投入するも案の定電源は入らず。
そう、玄箱の電源がお逝きになられた。こうなったら後の祭り。

へこみながらネットで情報を探してみると同じくショートさせてしまった人がいて
ヒューズを交換して復旧していた。

とりあえず、自分の場合もヒューズ切れでは?と思いデジタルマルチメータでヒューズ(F1)の導通を確認する。
結果、導通していない。つまりヒューズが切れている。
これはラッキーかもしれない。
というのもヒューズは保護回路で過剰電流や過剰電圧、異常温度になったときに回路が損傷しないように回路を遮断するためのものだから、ほかの部分が損傷してない可能性があるってことでラッキーかもしれない。
逆にヒューズの導通が確認できると、その他の部分が損傷していることになり、原因の特定が難しい。

さて、ネットの情報をもとにリード付きヒューズの3Aを秋葉原で探したところラジオセンターの小沼にあった。
2個で150円だった。さすが秋葉原だなぁと思いながら帰路につき、早速交換作業を行うと発覚した問題が

というのも、元々ついてヒューズはよく見ると2Aと書いてある。
ヒューズ自体は回路をつなぐだけのものだから3Aでも動くけれど、過電流際に2Aだったのもが3Aまで正常となってしまう。
これでは、過電流の際にヒューズ以外の部分を損傷する可能性が生まれるため、新たに交換する人は2Aを購入するように。

なお、購入したリード付きヒューズのリードは少し太めだったけれど問題なく換装できた。
そして、電源を投入すると無事起動できることを確認した。

2Aのリード付きヒューズを見つけたら交換しよう・・・

[VS]ソフトウェア発行元証明書の作成と署名

作成物に証明書を署名するための作成方法と署名方法をメモ。

自己署名証明書とか、オレオレ証明書とかいわれるものでVSTOのインストールにClickOnceを使用する場合、必要なもの。
使用するツールはWindowsSDKに含まれている。

  • 作成方法
    
    rem 1.====
    rem CA:Certificate Authority:認証局証明書
    rem  会社名 : MoonWing
    rem  組織名 : MoonWing Authority Root CA
    rem  県  名 : Tokyo
    rem  国  名 : JP
    rem 有効期限: 2012.12.31
    "%ProgramFiles%\Microsoft SDKs\Windows\v7.1\Bin\makecert" -r -n "C=JP, S=Tokyo, OU=MoonWing Authority Root CA, O=MoonWing" -e 12/31/2012 -a sha1 -cy authority -sv moonwingCA.pvk moonwingCA.cer
    rem 秘密キーのパスワードの作成:Subject Key:rootCA
    rem 秘密キーのパスワードの入力:Subject Key:rootCA
    
    rem 2.====
    rem EE:End Entity:署名用証明書
    rem コモン名: MoonWing
    rem  会社名 : MoonWing
    rem  組織名 : MoonWing Development
    rem  県  名 : Tokyo
    rem  国  名 : JP
    rem 有効期限: 2012.12.31
    "%ProgramFiles%\Microsoft SDKs\Windows\v7.1\Bin\makecert" -n "CN=MoonWing, C=JP, S=Tokyo, O=MoonWing, OU=MoonWing Development" -e 12/31/2012 -sv moonwing.pvk -ic moonwingCA.cer -iv moonwingCA.pvk -nscp -cy end moonwing.cer
    rem 秘密キーのパスワードの作成:Subject Key:endEntity
    rem 秘密キーのパスワードの入力:Subject Key:endEntity
    rem 秘密キーのパスワードの入力:Issuer Signature:rootCA
    
    rem 3.====
    rem SPC:Software Publisher's Certificate:ソフトウェア発行元証明書
    "%ProgramFiles%\Microsoft SDKs\Windows\v7.1\Bin\Cert2SPC" moonwing.cer moonwingCA.cer moonwing.spc
    
    rem 4.====
    rem PFX:Personal Information Exchange:PKCS#12
    rem  -pi(pvkpassword):endEntity
    rem  -po(pfxpassword):SPC
    "%ProgramFiles%\Microsoft SDKs\Windows\v7.1\Bin\pvk2pfx" -pvk moonwing.pvk -pi endEntity -spc moonwing.spc -pfx moonwing.pfx -po SPC
    
  • 署名方法
    
    rem 5.====
    rem target.exeへ署名
    rem  -t(time stamp server):http://timestamp.verisign.com/scripts/timstamp.dll
    rem  -p(pfxpassword):SPC
    "%ProgramFiles%\Microsoft SDKs\Windows\v7.1\Bin\signtool" sign /f moonwing.pfx /a /t http://timestamp.verisign.com/scripts/timstamp.dll /p SPC target.exe
    

[VS]PIA対応バージョンまとめ

PIAのバージョンとOfficeのバージョンと.NetFrameworkのバージョンの表をVSTO表のついでに作成。
PIAとはPrimaryInteropAssemblyことで・・・詳細はMicrosoftにお尋ねください。

PIA 対応Office 対応.NetFramework 対応Windows
XP XP 1.1 XP
2003 2003 1.1 2000 SP3,XP,Server 2003
2007 2007 1.1 2000 SP4,XP SP2,Server 2003
2010 2010 2.0 or higher 2000 SP4,XP SP2,Server 2003,Vista,7,Server 2008

[VS]VSTO対応バージョンまとめ

VSTOのバージョンとOfficeのバージョンと.NetFrameworkのバージョンの表がほしくなったので作成。
VSTOとは

  • Microsoft Visual Studio 2005 Tools for Office Second Edition Runtime
  • Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System
  • Microsoft Visual Studio Tools for the Microsoft Office system (Version 3.0 Runtime)
  • Microsoft Visual Studio 2010 Tools for the Microsoft Office System (Version 4.0 Runtime)

と微妙に名前が変わっているOffice拡張用コンポーネントのことです。
基本的には上記の2個目を省いた以下の3つあれば問題ないはず。
(というか、3個目も省いていいかも、結局2個で2003,2007,2010に対応できることになるわけだし。)

Vsto 対応Office 対応.NetFramework 対応VisualStduio 対応Windows
2005 SE 2003,2007 2.0 2005 2000,XP,Server 2003,Vista,7,Server 2008
3.0 2007 3.5 SP1 2008 2000,XP,Server 2003,Vista,7,Server 2008
4.0 2007,2010 3.5 SP1 2010 XP,Server 2003,Vista,7,Server 2008

ディレクティブ

クロスプラットフォーム対応コードを書くときにプラットフォーム依存部分を切り分けるプリプロセッサディレクティブのメモ。

  • Compiler
    • GCC
      • #ifdef __GNUC__
        • #if __GNUC__ >= 3 // GCC3.0以上
    • Borland C++
      • #ifdef __BORLANDC__
    • intel Compiler
      • #ifdef __INTEL_COMPILER
    • Microsoft Compiler
      • #ifdef _MSC_VER
        • #if _MSC_VER >=600 // C Compiler 6.0以降 VC++含む
        • #if _MSC_VER >=700 // C/C++ Compiler 7.0以降 VC++含む
        • #if _MSC_VER >=800 // VC++1.0以降
        • #if _MSC_VER >=900 // VC++2.0以降
        • #if _MSC_VER >=1000 // VC++4.0以降
        • #if _MSC_VER >=1010 // VC++4.1以降
        • #if _MSC_VER >=1020 // VC++4.2以降
        • #if _MSC_VER >=1100 // VC++5.0以降
        • #if _MSC_VER >=1200 // VC++6.0以降
        • #if _MSC_VER >=1300 // VC2002(VC7.0)以降
        • #if _MSC_VER >=1310 // VC2003(VC7.1)以降
        • #if _MSC_VER >=1400 // VC2005(VC8.0)以降
        • #if _MSC_VER >=1500 // VC2008(VC9.0)以降
        • #if _MSC_VER >=1600 // VC2010(VC10.0)以降
  • UNIX system
    • UNIX
      • #ifdef __unix
      • #ifdef __unix__
    • Linux
      • #ifdef __linux
      • #ifdef __linux__
    • FreeBSD
      • #ifdef __FreeBSD__
    • NetBSD
      • #ifdef __NetBSD__
    • Cygwin
      • #ifdef __CYGWIN__
      • #ifdef __CYGWIN32__ // 32bit版Cygwin
    • MinGW (-mno-cygwin)
      • #ifdef __MINGW32__
  • Windows system
    • CUI
      • #ifdef _CONSOLE
    • GUI
      • #ifdef _WINDOWS
    • 32bit Windows
      • #ifdef WIN32
      • #ifdef _WIN32
    • 64bit Windows
      • #ifdef _WIN64
    • Windows version
      • #ifdef WINVER
        • #if (WINVER >= 0x030a) // Windows 3.1以降
        • #if (WINVER >= 0x0400) // Windows 95/ NT4.0以降
        • #if (WINVER >= 0x0410) // Windows 98以降
        • #if (WINVER >= 0x0500) // Windows Me/ 2000以降
        • #if (WINVER >= 0x0501) // Windows XP/ Server 2003以降
        • #if (WINVER >= 0x0502) // Windows XP SP2/ Server 2003 SP1以降
        • #if (WINVER >= 0x0600) // Windows Vista/ Server 2008以降
        • #if (WINVER >= 0x0601) // Windows 7以降
      • #ifdef _WIN32_WINDOWS // Windows9x
        • #if (_WIN32_WINDOWS >= 0x0400) // Windows 95以降
        • #if (_WIN32_WINDOWS >= 0x0410) // Windows 98以降
        • #if (_WIN32_WINDOWS >= 0x0500) // Windows Me以降
      • #ifdef _WIN32_WINNT // WindowsNTx
        • // Windows 2000以降(0x0500)
          #if (_WIN32_WINNT >= _WIN32_WINNT_WIN2K)
        • // Windows XP/ Server 2003以降(0x0501)
          #if (_WIN32_WINNT >= _WIN32_WINNT_WINXP)
        • // Windows XP SP2/ Server 2003 SP1以降(0x0502)
          #if (_WIN32_WINNT >= _WIN32_WINNT_WS03)
        • // Windows Vista以降(0x0600)
          #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
        • // Windows Server 2008以降(0x0600)
          #if (_WIN32_WINNT >= _WIN32_WINNT_WS08)
        • // Windows 7以降(0x0601)
          #if (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
      • #ifdef _WIN32_WCE // WindowsCE
        • #if (_WIN32_WCE >= 0x0420) // Windows Mobile 2003(PPC2003)
        • #if (_WIN32_WCE >= 0x0421) // Windows Mobile 2003 SE(PPC2003SE)
        • #if (_WIN32_WCE >= 0x0501) // Windows Mobile 5.0
        • #if (_WIN32_WCE >= 0x0502) // Windows Mobile 6 Professional / Classic
        • #if (WINCEOSVER >= 0x0300) // WindowsCE3.0(PPC2002)以降
        • #if (WINCEOSVER >= 0x0420) // WindowsCE4.2(PPC2003)以降
        • #if (WINCEOSVER >= 0x0500) // WindowsCE5.0(WM5.0)以降
    • Internet Explorer version
      • #ifdef _WIN32_IE
        • #if (_WIN32_IE>=0x0200) // Windows 95/NT 4.0(Comctl32.dll 4.00, Shell32.dll 4.00)
        • #if (_WIN32_IE>=0x0300) // Internet Explorer 3.0, 3.01, 3.02
        • #if (_WIN32_IE>=0x0400) // Internet Explorer 4.0
        • #if (_WIN32_IE>=0x0401) // Internet Explorer 4.01
        • #if (_WIN32_IE>=0x0500) // Internet Explorer 5.0, 5.0a, 5.0b
        • #if (_WIN32_IE>=0x0501) // Internet Explorer 5.01
        • #if (_WIN32_IE>=0x0550) // Internet Explorer 5.5
        • #if (_WIN32_IE>=0x0600) // Internet Explorer 6.0
        • #if (_WIN32_IE>=0x0601) // Internet Explorer 6.0 SP1
        • #if (_WIN32_IE>=0x0603) // Internet Explorer 6.0 SP2
        • #if (_WIN32_IE>=0x0700) // Internet Explorer 7.0
        • #if (_WIN32_IE>=0x0800) // Internet Explorer 8.0

注意
プリプロセッサは、未定義の識別子を0として扱うため、#if __GNUC__ >= 3はGCC3以上として使えるが、
GCC2系かどうかを#if __GNUC__ < 3で判定しようとすると、GCCでないものも含まれる。
参考