2011/10/26

エクセル帳票出力の並列実行 その2 (Excel file parallel processing, Part 2)


前回の並列実行の検証では、物理コア数までは並列度にしたがって出力性能が向上するものの、伸び率については、並列度が4倍(1→4)に増えても処理性能は2.3倍(秒間4.5ファイル→10.3ファイル)程度の伸び率にとどまることが確認されました。
今回は、この事象をOS統計から確認します。

【CPU】
CPU使用率の推移は以下の通りです。
※なお、検証環境の物理コア数は4です。
Figure 3: CPU usage

1スレッドでの実行においても、コアをまたがって処理負荷が分散されています。常に5つのコアがそれぞれ60%程度の使用率で推移しており、全体での使用率は約40%(300% ÷ 800%)です。従って、CPU容量に対する伸びしろはこの時点で最大2.5倍しか残されていないと言えます。

2スレッドでは、すべてのコアに処理負荷がかかっています。各コアの使用率はそれぞれ約60%、全体としての使用率も同じく60%です。
4スレッドで各コアの使用率が90%を超えます。また、5スレッド以降のCPU使用率の動きは、他のボトルネックによってCPUの動きが妨げられている可能性を示しています。

実行モードの内訳を確認すると、Priviledged Time (sys)が2割近くを占めています。
Figure 4: CPU mode

コンテキスト・スイッチ(Context Switches)の状態は以下の通りです。以前の検証でも高い値を記録していましたが、今回も同様です。
Figure 5: Context Switches

プロセッサ・キュー(Processor Queue Length)の値は4スレッドから目立ち始め、5スレッド以降は過負荷であることを示しています。
Figure 6: Processor Queue Length

【メモリ】
スレッド数の増加に伴って開きメモリが減っていきますが、6GB以上の余裕があります。
グラフは割愛しますが、ページングも発生しておらず、問題は見られません。
Figure 7: Memory

【ディスク】
4スレッドまでは問題ありません。5スレッド以降はDisk Timeの値が増加し始めます。
Figure 8: Disk Time (1 - Idle Time)

同様に、5スレッド以降、キューの滞留が徐々に増えています。
Figure 9: Disk Queue Length

【結論】
エクセルによる帳票出力(COMによる操作)はCPUの処理容量に依存しやすいと言えます。
また、エクセルのアプリケーション自体が10以上のプロセスを保持し、マルチスレッド処理を行っているため、エクセルのアプリケーションそのものを複数、並列に処理する場合でも処理性能が並列度に対してリニアに向上しないという点に留意する必要があります。


[Summary]
In the last post, multi thread processing had got poor result.  The maximum performance is 10.3 files per sec (130% increase) with four threads.
OS statistics explains the detail of this problem.


[CPU]
Figure 3 shows the CPU usage, from 1 to 8 threads.  The single thread test case(left side) uses 5 cores.  Overall CPU usage is about 40%, so the remained CPU resource is 60%.  This means that maximum performance increase ratio is 150% more ( 60 / 40 = 1.5).


Same as the past test (the original sample program), Priviledged Time (sys) gets higher than the ordinary level (Figure 4).
Context Switches seems bad in Figure 5.  Its trend is mostly same as CPU usage.
Processor Queue Length gets high from 5 to 8 threads (Figure 6).  This means too much threads causes collision and it leads lower performance.


[Memory]
Figure 7.  There seems no problem.


[Disk]
Figure 8 and 9.  Through 1 to 4 threads, no problem.  From 5 threads, Disk Time and Disk Queue Length get higher.


[Conclusion]
Excel file processing (Excel COM operation) is CPU bound.
Excel application itself manages more than 10 processes within , and perform multi thread processing.  This architecture might increase the single running performance though, there's few room to increase with running Excel application in parallel.

2011/10/25

エクセル帳票出力の並列実行 その1 (Excel file parallel processing, Part 1)

これまでの検証で、1ファイルあたりの処理時間は0.22秒まで短縮されました。処理性能は1秒当たり4.5ファイルとなります。
今回は並列処理で単位時間当たりの処理能力の向上を図り、どの程度リニアに性能が向上するかを検証します。

【検証の方法について】
通常の運用であれば、スケジューラのジョブを並列実行させますが、今回のサンプルではプログラム内で複数スレッドを生成することで検証を行います。
検証環境は「エクセルファイルのバッチ出力 その5」と同様です。なお、今回はデバッグモードではなく、アプリケーション(.exe)を直接実行します。

【サンプルソース(GUI部)】
サンプルのソースの内、呼び出し側(GUI側)を以下の様に修正します。並列度はスライダーで指定し、並列度を1から8(論理コア数)まで変化させます。
並列実行はSystems.Threads.Tasksに含まれるParallel.Forを使用します。スレッド毎に個別のオブジェクト(エクセルおよびDBセッションを保持する)を起動し、スレッド間の競合回避を図ります。
Figure 1: Form

List 1:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Util;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

 

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int num_threads = trackBar1.Value;
            List<Util.Ora2Excel> lst = new List<Util.Ora2Excel>();

            // initialize
            for (int i = 0; i < num_threads; i++)
            {
                lst.Add(new Util.Ora2Excel());
                lst[i].OpenDb(txtUser.Text, txtPassword.Text, txtConnString.Text);
                lst[i].InitExcel();
            }

            DateTime startTime = DateTime.Now;

            Parallel.For(0, num_threads, threadID =>
            {
                for (int idx = 0; idx < 100; idx++)
                {
                    lst[threadID].OpenBook(@"c:\template_emp.xlsx", true);
                    lst[threadID].Extract(txtSql.Text, txtSheet.Text);
                    lst[threadID].SaveBook(@"c:\" + threadID.ToString() + @"\result_emp" + "_" + threadID.ToString() + "_" + idx.ToString() + ".xlsx");
                    lst[threadID].CloseBook();
                }
            });
            
            // write the result
            System.IO.StreamWriter sw = new System.IO.StreamWriter(@"c:\testResult.log", true);
            sw.WriteLine("threads: " + num_threads.ToString() + ", "  + (DateTime.Now - startTime).ToString());
            sw.Close();
            
            // close objects
            for (int j = 0; j < num_threads; j++)
            {
                lst[j].QuitExcel();
                lst[j].CloseDb();
            }

        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            lblThreads.Text = "threads: " + trackBar1.Value.ToString();
        }
    }
}

【サンプルソース(DLL部)】
DLL部のソースに変更はありません。ソースは「エクセルファイルのバッチ出力 その3」を参照してください。

結果は以下の通りです。4多重まで増加させた場合でも、シングルスレッド実行の場合の約2倍の性能向上にとどまりました。秒間10.3ファイルの出力性能です。性能の向上率は高いとは言えません。
また、4コア以降、多重度を上げるにつれて性能が劣化しています。
Figure 2: Performance result

次回はOS統計を確認します。


[Summary]
In this post, we'll see how much we can increase Excel file processing performance by parallel (multi thread) processing.


[Environment]
Please refer to Excel file processing, Part 5.


[Sample source (GUI)]
In the ordinary batch system,you may run programs by job scheduler parallel.  In this test, I implement multi thread processing within the sample program.  Please refer Figure 1 and List 1.  The slider at the bottom of the form specifies the number of threads.  Each thread owns individual database session and Excel object.


[Sample source (DLL)]
No changes have been made.  Please refer to Excel file processing, Part 3 for the source code.


[Result]
As shown in Figure 2, the result is not so good.  The output performance hit the peak with four threads.  The peak performance is 10.3 files per sec. (100% increase from single thread performance)


In the next post, we read the OS statistics.

2011/10/17

エクセルファイルのバッチ出力 その6 (Excel file processing, Part 6)

ここで一度、サンプルプログラム実行時のマシン負荷を確認します。
今回はプログラムを素で実行し(デバッグモードではなく、EXEを直接起動)、OS統計を収集しました。
統計の取得間隔は2秒です。

【CPU】
論理8コア(物理4コア)の内、コアを4つ使用しています。各コアの使用率は50%程度で推移しており、全体としてのCPU使用率は約25%です。
Figure 11: CPU usage during the Excel file processing

CPU使用率の内訳を確認します。全体でのPrivileged TimeとUser Time(sys、user)の使用率は以下の通りです。Privileged Timeが若干ですが目立ちます。
Figure 12: CPU mode

念のためコンテキストスイッチ(Context Switches)を確認します。高い値で推移しています。Excel 2010では過去のバージョンよりも多くのスレッドが使用されているため、今回のような使用パターンでは値が高止まりしやすいと推測されます。
Figure 13: Context switches


また、エクセルのプロセスを抽出したCPUの使用率の推移は以下の通りです。約200%で推移しており、前述のCPU使用率(全体で25%)と概ね一致しています。
Figure 14: CPU usage of Excel process


今回はDBサーバが同一機材上のVMに構築されているため、VMのCPU使用状況も確認します。最大でも(800%中)約6%と、ほぼ凪であり、影響は概ね無視できると考えられます。
Figure 15: CPU usage of the VM processes


【メモリ】
メモリは余裕のある状態です。グラフは割愛しますが、ページングも発生しておらず、問題は認められません。
Figure 16: Memory usage


【ディスク】
ディスクも余裕のある状態です。問題は認められません。
Figure 17: Disk usage

今回の検証では、エクセル操作はCPUへの負荷が非常に高いことが確認されました。これらの値を踏まえた上で、次回はサンプルアプリにて並列処理を検証します。



[Summary]
Figures above show the OS statistics during the sample program processing.

[CPU]
Figure 11 shows that the sample program (and Excel process) uses 4 cores (Intel Core i7: 4 cores w/ HT).  Each cores are used around 50%.

Figure 12 shows Privileged Time and User Time in total.  the Privileged Time is higher than ordinary level.

Figure 13 shows Context Switches get high level.  Since Excel 2010 handles more threads than the past version (Excel 2003 and older), the overhead of context switch becomes bigger issue.

Figure 14 and 15 show CPU usage of Excel process and DB server on the virtual machine.  The CPU usage of VM is low enough to be ignored.

[Memory]
no problem with the memory (Figure 16).

[Disk]
Disk is not busy at all (Figure 17).

The result shows that Excel operation costs CPU resource.  I will test parallel processing in the next post.