関連記事
- 今週もひたすらモノ書き #JAVA 祭りがまだまだ続く そろそろC#を書かせろー 【2024年12月04日(水)】
- 【#CSHARP】ソリューション内でサービス,Winformアプリを混在で作成させ,バイナリ出力先を同じにするとサービスが起動しない 【2024年02月08日(木)】
- 【#PHP】謎な #Laravel 案件 引き渡したじ 【2024年01月11日(木)】
- 【C#】謎な改造アプリ,SIMD命令を導入して高速化しようか,思案中 【2023年11月14日(火)】
- Javaの”やらかし”でC#と人気逆転か 激変プログラミング言語人気ランキング 【2023年10月18日(水)】
Core2Quadで、実験したマルチスレッドグレースケール処理の記事を掲載しました
こちらをご覧ください
前回、グレースケール処理でInt* Byte*、どっちの処理が速いか?ってことを、
テストしてみたけど、あまり、速度上がらず…(´・ω・`)
激怒しちゃったんで、このグレースケール処理、マルチスレッド化してみた(w
いつものように条件は以下のとおり
CPU : AMD Athlon64x2 3800+(2.0GHz)
Memory : 1GB
OS : Windows XP Pro
言語: Visual Studio 2005(C#2.0) + .Net FrameWork2.0
画像データ1000回の グレースケール処理を実行 |
リリースコンパイル |
640 * 480 24ビットピクセル 1スレッド |
11,703ミリ秒 |
640 * 480 24ビットピクセル 2スレッド |
7,843ミリ秒 |
640 * 480 24ビットピクセル 4スレッド |
7,390ミリ秒 |
う~む、余は満足じゃ!
それにしても、4コアで試してみたいなぁ。。。
もうちょっとしたら、4コアに変えるんで、そのとき再度、性能評価やってみよう…
コードは、4スレッド版です
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace GrayScaleTest
{
public partial class Form1 : Form
{
private const int THREADCOUNT = 5;
static public Form1 m_MyObj; //スレッドへ情報を渡すため、自分自身のインスタンスをセット
private Bitmap m_ImageBackup; // 一時データ
private Bitmap m_bmapIn; // 入力データ
private Bitmap m_bmapOut; // 出力データ
private bool m_ThreadOnFL;
private bool[] m_ThreadJobFL;
private bool[] m_ThreadJobFixFL;
private Thread[] m_Thread;
private IntPtr m_SouPT;
private IntPtr m_DesPT;
private int m_Width; // Image サイズ
private int m_Height; // Image サイズ
public Form1()
{
InitializeComponent();
m_MyObj = this;
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Image = null;
m_ThreadOnFL = true;
m_ThreadJobFL = new bool[THREADCOUNT];
m_ThreadJobFixFL = new bool[THREADCOUNT];
for (int i = 0; i < THREADCOUNT; i++)
{
m_ThreadJobFL[i] = false;
m_ThreadJobFixFL[i] = false;
}
m_Thread = new Thread[THREADCOUNT];
m_Thread[0] = new Thread(new ThreadStart(ThreadMethod0));
m_Thread[1] = new Thread(new ThreadStart(ThreadMethod1));
m_Thread[2] = new Thread(new ThreadStart(ThreadMethod2));
m_Thread[3] = new Thread(new ThreadStart(ThreadMethod3));
m_Thread[4] = new Thread(new ThreadStart(ThreadMethod4));
m_Thread[0].Name = "画像処理スレッド0";
m_Thread[1].Name = "画像処理スレッド1";
m_Thread[2].Name = "画像処理スレッド2";
m_Thread[3].Name = "画像処理スレッド3";
m_Thread[4].Name = "画像処理スレッド4";
m_Thread[0].Start();
m_Thread[1].Start();
m_Thread[2].Start();
m_Thread[3].Start();
m_Thread[4].Start();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
m_ThreadOnFL = false;
for(int i = 0; i < 200; i++)
{
Application.DoEvents();
Thread.Sleep(1);
}
}
private void button1_Click(object sender, EventArgs e)
{
string FileName;
if (openFileDialog1.ShowDialog() != DialogResult.OK)
{
return;
}
FileName = openFileDialog1.FileName;
m_ImageBackup = new Bitmap(FileName);
m_Width = m_ImageBackup.Width;
m_Height = m_ImageBackup.Height;
m_bmapOut = new Bitmap(m_Width, m_Height);
m_bmapIn = m_ImageBackup;
pictureBox1.Image = m_bmapIn;
}
private void JobCore_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
int min = dt.Minute;
int sec = dt.Second;
int mili = dt.Millisecond;
lblStart.Text = "";
lblEnd.Text = "";
lblJob.Text = "";
lblStart.Text = "開始時間:" + min.ToString() + "_" + sec.ToString() + "_" + mili.ToString();
Refresh();
Bitmap bd = pictureBox1.Image as Bitmap;
Bitmap bs;
BitmapData bDataInS;
BitmapData bDataInD;
IntPtr Scan0_InS; // ピクセルデータの開始アドレス
IntPtr Scan0_InD; // ピクセルデータの開始アドレス
bs = new Bitmap(m_bmapIn);
bDataInS = bs.LockBits(new Rectangle(0, 0, bs.Width, bs.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
Scan0_InS = bDataInS.Scan0; // ピクセルデータの開始アドレス
bDataInD = bd.LockBits(new Rectangle(0, 0, bd.Width, bd.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
Scan0_InD = bDataInD.Scan0; // ピクセルデータの開始アドレス
m_SouPT = Scan0_InS;
m_DesPT = Scan0_InD;
m_Width = bd.Width;
m_Height = bd.Height;
if (sender == button2)
{
for(int j = 1; j < THREADCOUNT; j++)
{
m_ThreadJobFixFL[j] = true; //スレッド処理完了フラグ (0番以外は完了させておく)
m_ThreadJobFL[j] = false; //スレッド処理開始フラグ(0番起動 以外は停止)
}
for(int i = 0; i < 1000; i++) //スレッド0番(480ライン処理)のみ起動
{
m_ThreadJobFixFL[0] = false; //スレッド処理完了フラグ (0番以外は完了させておく)
m_ThreadJobFL[0] = true; //スレッド処理開始フラグ(0番起動 以外は停止)
while(IsThreadJobFix() == false ) //全スレッドの処理が完了するまで待機
{
Thread.Sleep(1);
}
}
}
else
{
m_ThreadJobFixFL[0] = true; //スレッド処理完了フラグ (0番は完了させておく)
m_ThreadJobFL[0] = false; //スレッド処理開始フラグ(0番停止 以外は起動)
for(int i = 0; i < 1000; i++) //スレッド1番2番(240ライン処理)のみ起動
{
for(int j = 1; j < THREADCOUNT; j++)
{
m_ThreadJobFixFL[j] = false; //スレッド処理完了フラグ (0番は完了させておく)
m_ThreadJobFL[j] = true; //スレッド処理開始フラグ(0番停止 以外は起動)
}
while(IsThreadJobFix() == false ) //全スレッドの処理が完了するまで待機
{
Thread.Sleep(1);
}
}
}
bd.UnlockBits(bDataInD);
bs.UnlockBits(bDataInS);
DateTime dt2 = DateTime.Now;
min = dt2.Minute;
sec = dt2.Second;
mili = dt2.Millisecond;
lblEnd.Text = "終了時間:" + min.ToString() + "_" + sec.ToString() + "_" + mili.ToString();;
TimeSpan tm = dt2.Subtract(dt);
lblJob.Text = "経過時間:" + tm.TotalSeconds.ToString();
//pictureBox1.Refresh();
Refresh();
}
//すべてのスレッドの処理が完了したらTrue
private bool IsThreadJobFix()
{
for(int i = 0; i < THREADCOUNT; i++)
{
if (m_ThreadJobFixFL[i] == false)
{
return false;
}
}
return true;
}
//スレッド向けコールバック関数(0番)
private static void ThreadMethod0()
{
m_MyObj.ThreadMainJob0();
}
//スレッド向けコールバック関数(1番)
private static void ThreadMethod1()
{
m_MyObj.ThreadMainJob1();
}
//スレッド向けコールバック関数(2番)
private static void ThreadMethod2()
{
m_MyObj.ThreadMainJob2();
}
//スレッド向けコールバック関数(3番)
private static void ThreadMethod3()
{
m_MyObj.ThreadMainJob3();
}
//スレッド向けコールバック関数(4番)
private static void ThreadMethod4()
{
m_MyObj.ThreadMainJob4();
}
//スレッドによるグレースケール処理
private void ThreadMainJob0()
{
while(m_ThreadOnFL == true)
{
if (m_ThreadJobFL[0] == false)
{
Thread.Sleep(1);
continue;
}
GrayScaleB(0, 480, m_SouPT, m_DesPT, m_Width, m_Height);
m_ThreadJobFL[0] = false;
m_ThreadJobFixFL[0] = true;
}
}
private void ThreadMainJob1()
{
while(m_ThreadOnFL == true)
{
if (m_ThreadJobFL[1] == false)
{
Thread.Sleep(1);
continue;
}
GrayScaleB(0, 120, m_SouPT, m_DesPT, m_Width, m_Height);
m_ThreadJobFL[1] = false;
m_ThreadJobFixFL[1] = true;
}
}
private void ThreadMainJob2()
{
while(m_ThreadOnFL == true)
{
if (m_ThreadJobFL[2] == false)
{
Thread.Sleep(1);
continue;
}
GrayScaleB(120, 240, m_SouPT, m_DesPT, m_Width, m_Height);
m_ThreadJobFL[2] = false;
m_ThreadJobFixFL[2] = true;
}
}
private void ThreadMainJob3()
{
while(m_ThreadOnFL == true)
{
if (m_ThreadJobFL[3] == false)
{
Thread.Sleep(1);
continue;
}
GrayScaleB(240, 360, m_SouPT, m_DesPT, m_Width, m_Height);
m_ThreadJobFL[3] = false;
m_ThreadJobFixFL[3] = true;
}
}
private void ThreadMainJob4()
{
while(m_ThreadOnFL == true)
{
if (m_ThreadJobFL[4] == false)
{
Thread.Sleep(1);
continue;
}
GrayScaleB(360, 480, m_SouPT, m_DesPT, m_Width, m_Height);
m_ThreadJobFL[4] = false;
m_ThreadJobFixFL[4] = true;
}
}
public void GrayScaleB(int startY, int endY, IntPtr ptS, IntPtr ptD, int tmpWidth, int tmpHeight)
{
int x, y;
int index;
byte PixelData;
byte red, green, blue;
int scanl = tmpWidth * 3;
unsafe
{
byte* ps = (byte*)ptS;
byte* pd = (byte*)ptD;
for (y = startY; y < endY; y++)
{
for (x = 0; x < scanl; x += 3)
{
index = (y * scanl) + x;
blue = ps[index ];
green = ps[index + 1];
red = ps[index + 2];
PixelData = (byte)(0.299f * ((float)red) + 0.587f * ((float)green) + 0.114f * ((float)blue));
pd[index] = PixelData;
pd[index + 1] = PixelData;
pd[index + 2] = PixelData;
}
}
}
}
}
}
[/csharp]
コメント
【#閃輝暗点】閃輝暗点が始まった!いつもどおり目が見えなくなってるー(汗
【#イプシロン】イプシロンSロケット 燃焼試験中に爆発事故発生
あっちもこっちも風邪が流行ってるの.外に出たら感染する勢い!
【訃報】俳優 火野正平さん死去 75歳
【地震】日向灘でM4.4の地震
【#第三次世界大戦】ウクライナ空軍 “ICBM1発がロシア南部から発射された”
司法省 “グーグルはクローム売却を” 裁判所に要求へ 米報道
最近,仕事がずっと激しい...ドロドロドロ
今日は謎の宴会らしい...スーツが入るのかっ!?(GRB爆
「侍ジャパン」宮崎県入り 「プレミア12」向け きょうから合宿