Xbyak

Top / misc / Xbyak
 

ページ構成
−Top
  • +Coding
  • +Server
  • +memo
  • −misc
    • ・3Dデータを元にプロトタイプ作成
    • ・Ateam
    • +Hardware
    • ・LCC
    • ・OutlookからThunderbirdへの移行
    • ・PC業界における法則
    • ・PR作成
    • ・TVのリモート視聴機能
    • ・WindowsXPから7への移行
    • ・Xbyak
    • ・podcast
    • ・いるもの
    • ・ごちゃまぜ
    • +ごはん
    • ・オープンソースハードウェア
    • ・コイルに関して
    • +ソフトウェア
    • ・プロジェクトの管理方法
    • ・ホームページデザイン参考
    • ・ポストイット、KJ法
    • ・マニュアル作成指針
    • ・マルチモニタの利点
    • ・メールの書き方
    • ・レビューサイトにおけるコメントシステムとコメントの質についての
    • +ロードバイク
    • ・一風変わった国内メーカ
    • ・映像関連技術
    • ・英語スペルミスDB
    • ・英語論文の書き方
    • ・怪談
    • +企業
    • ・敬語について
    • ・個人でアルミ加工依頼可能
    • ・撮影ポイント
    • ・紙幣偽造防止の仕組み
    • ・事務作業
    • ・自分への問いかけ
    • ・鹿児島
    • ・条文をテキストデータで入手可能なところ
    • ・青色申告
    • ・大阪市内病院
    • ・登山
    • ・日本庭園
    • ・日本庭園特集
    • ・認証画面
    • ・不正アクセス禁止法に関して
    • +勉強会メモ
    • +翻訳
    • ・未読
    • ・面白いサイト(写真関連)
    • ・料理
  • +カメラ
  • +科学技術
  • +記事
  • +数値解析
最新の10件
2018-01-16 更新
  • misc/Hardware/各種プロセッサの倍精度演算性能
2017-11-27 更新
  • Coding/misc/raspberrypi
2017-11-02 更新
  • Coding/.NET/NuGetパッケージの作成
2017-10-19 更新
  • Coding/MSOffice/VSTO/ThisAddin_Startupに処理を書く問題が起きる
2017-06-16 更新
  • Coding/.NET/VisualStudioビルドイベント
2017-05-28 更新
  • misc/Hardware/タブレット向けCPU/複製
2017-05-25 更新
  • Coding/Python/CloudVision
2017-05-24 更新
  • misc/ロードバイク/サイクルロード/奈良
2017-05-11 更新
  • misc/ソフトウェア/文章/文章校正、作成支援ツール
2017-03-15 更新
  • misc/ソフトウェア/プロジェクト管理ツール

Powered By

b_pukiwiki.official.png

edit

x86/x64最適化勉強会2 : ATND
http://atnd.org/events/19140

/*
	@author herumi
	@date $Date: 2008/04/29 11:29:04 $

	JPEG quantize sample
	This program generates a quantization routine by using fast division algorithm in run-time.

	time(sec)
	quality  1(low) 10     50   100(high) 
	VC2005   8.0     8.0   8.0  8.0 
	Xbyak    1.6     0.8   0.5  0.5 


; generated code at q = 100
    push        esi
    push        edi
    mov         edi,dword ptr [esp+0Ch]
    mov         esi,dword ptr [esp+10h]
    mov         eax,dword ptr [esi]
    shr         eax,4
    mov         dword ptr [edi],eax
    mov         eax,dword ptr [esi+4]
    mov         edx,0BA2E8BA3h
    mul         eax,edx
    shr         edx,3
    ...

; generated code at q = 100
     push        esi
     push        edi
     mov         edi,dword ptr [esp+0Ch]
     mov         esi,dword ptr [esp+10h]
     mov         eax,dword ptr [esi]
     mov         dword ptr [edi],eax
     mov         eax,dword ptr [esi+4]
     mov         dword ptr [edi+4],eax
     mov         eax,dword ptr [esi+8]
     mov         dword ptr [edi+8],eax
     mov         eax,dword ptr [esi+0Ch]
	 ...

*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "xbyak/xbyak.h"
#ifdef _WIN32
	#pragma warning(disable : 4996) // scanf
#endif

typedef Xbyak::uint64 uint64;
typedef Xbyak::uint32 uint32;

const int N = 64;

class Quantize : public Xbyak::CodeGenerator {
	static int ilog2(int x)
	{
		int shift = 0;
		while ((1 << shift) <= x) shift++;
		return shift - 1;
	}
public:
	/*
		input : esi
		output : eax = [esi+offset] / dividend
		destroy : edx
	*/
	void udiv(uint32 dividend, int offset)
	{
		mov(eax, ptr[esi + offset]);

		/* dividend = odd x 2^exponent */
		int exponent = 0, odd = dividend;
		while ((odd & 1) == 0) {
			odd >>= 1; exponent++;
		}

		if (odd == 1) { // trivial case
			if (exponent) {
				shr(eax, exponent);
			}
			return;
		}

		uint64 mLow, mHigh;
		int len = ilog2(odd) + 1;
		{
			uint64 roundUp = uint64(1) << (32 + len);
			uint64 k = roundUp / (0xFFFFFFFFL - (0xFFFFFFFFL % odd));
			mLow = roundUp / odd;
			mHigh = (roundUp + k) / odd;
		}

		while (((mLow >> 1) < (mHigh >> 1)) && (len > 0)) {
			mLow >>= 1; mHigh >>= 1; len--;
		}

		uint64 m; int a;
		if ((mHigh >> 32) == 0) {
			m = mHigh; a = 0;
		} else {
			len = ilog2(odd);
			uint64 roundDown = uint64(1) << (32 + len);
			mLow = roundDown / odd;
			int r = (int)(roundDown % odd);
			m = (r <= (odd >> 1)) ? mLow : mLow + 1;
			a = 1;
		}
		while ((m & 1) == 0) {
			m >>= 1; len--;
		}
		len += exponent;

		mov(edx, int(m));
		mul(edx);
		if (a) {
			add(eax, int(m));
			adc(edx, 0);
		}
		if (len) {
			shr(edx, len);
		}
		mov(eax, edx);
	}
	/*
		quantize(uint32 dest[64], const uint32 src[64]);
	*/
	Quantize(const uint32 qTbl[64])
	{
		push(esi);
		push(edi);
		const int _P = 4 * 2;
		mov(edi, ptr [esp+_P+4]); // dest
		mov(esi, ptr [esp+_P+8]); // src
		for (int i = 0; i < N; i++) {
			udiv(qTbl[i], i * 4);
			mov(ptr[edi+i*4], eax);
		}
		pop(edi);
		pop(esi);
		ret();
	}
};

void quantize(uint32 dest[64], const uint32 src[64], const uint32 qTbl[64])
{
	for (int i = 0; i < N; i++) {
		dest[i] = src[i] / qTbl[i];
	}
}

int main(int argc, char *argv[])
{
#ifdef XBYAK64
	puts("not implemented for 64bit");
	return 1;
#endif
	int q;
	if (argc > 1) {
		q = atoi(argv[1]);
	} else {
		printf("input quantize=");
		scanf("%d", &q);
	}
	printf("q=%d\n", q);
	uint32 qTbl[] = {
		16, 11, 10, 16, 24, 40, 51, 61,
		12, 12, 14, 19, 26, 58, 60, 55,
		14, 13, 16, 24, 40, 57, 69, 56,
		14, 17, 22, 29, 51, 87, 80, 62,
		18, 22, 37, 56, 68, 109, 103, 77,
		24, 35, 55, 64, 81, 104, 113, 92,
		49, 64, 78, 87, 103, 121, 120, 101,
		72, 92, 95, 98, 112, 100, 103, 99
	};

	for (int i = 0; i < N; i++) {
		qTbl[i] /= q;
		if (qTbl[i] == 0) qTbl[i] = 1;
	}

	try {
		uint32 src[N];
		uint32 src2[N];
		uint32 dest[N];
		uint32 dest2[N];
		for (int i = 0; i < N; i++) {
			src2[i] = src[i] = rand() % 2048;
		}

		Quantize jit(qTbl);
//printf("jit size=%d, ptr=%p\n", jit.getSize(), jit.getCode());
		void (*quantize2)(uint32*, const uint32*, const uint32 *) = (void (*)(uint32*, const uint32*, const uint32 *))jit.getCode();

		quantize(dest, src, qTbl);
		quantize2(dest2, src, qTbl);
		for (int i = 0; i < N; i++) {
			if (dest[i] != dest2[i]) {
				printf("err[%d] %d %d\n", i, dest[i], dest2[i]);
			}
		}

		const int count = 10000000;
		int begin;

		begin = clock();
		for (int i = 0; i < count; i++) {
			quantize(dest, src, qTbl);
		}
		printf("time=%.1fsec\n", (clock() - begin) / double(CLOCKS_PER_SEC));

		begin = clock();
		for (int i = 0; i < count; i++) {
			quantize2(dest, src, qTbl);
		}
		printf("time=%.1fsec\n", (clock() - begin) / double(CLOCKS_PER_SEC));
	} catch (Xbyak::Error err) {
		printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
	} catch (...) {
		printf("unknown error\n");
	}
	return 0;
}

トップ   編集 凍結 差分 添付 複製 名前変更 リロード   新規 一覧 単語検索   ヘルプ   最終更新のRSS
Last-modified: 2011-12-14 (水) (2322d)
Site admin: D*isuke YAMAKAWA

PukiWiki 1.4.7 Copyright © 2001-2006 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji. Powered by PHP 5.3.29. HTML convert time: 0.029 sec.