wrongwrongな開発日記

情報系大学院生の忘備録

購入前、自作erなら知っておいて損はないサイト紹介

自作PCを作る前に知っておいて損はない、自分が使っている/使ったことのある基本的なサイトをまとめます。

総合的な情報量が魅力、価格.com

kakaku.com

自作PCを作るなら、価格.comはかなりの量の情報を探せるので、まず最初に見るサイトとしてオススメです。

レビューもそれなりに充実していますし、ピックアップリストや口コミ掲示板への書き込みという形で質問もできます。簡単な質問であればほぼ100%返信が来ます。

注意点としては、時々キツめな返信があったり、レビューも玉石混交で、知識が無ければ判断し辛いことでしょうか。

特に、データや根拠を示していないレビューでも、好評や悪評として最初に目に入ってしまうのは分かっておいた方が良いかもしれません。

価格.comでは十分な情報を集めにくい製品があったり、価格.comでは販売している店が無いとなっていても、実際に調べてみると販売している店があったり、最安値が違っていたりする場合もあります。こういった理由もあり、価格.comは、初めに見るサイトとしてはおすすめですが、全部を頼るべきではないかな、というのが自分の意見です。

レビューとポイント

価格.comでは、レビュー投稿でKC Point(1ポイント≒1円)が手に入るキャンペーンを毎月実践していて、これがまあまあお得です。

前月から連続レビューで300ポイント、その製品への初めてのレビューなら50ポイント、レビューした製品が発売から1年以内なら50ポイント手に入ります。

月1度投稿を繰り返していけば1年で3600円、Amazonギフト券iTunesカードと交換できるので、自作erじゃなくても使いみちは結構あります。

まあ、バイトとかに比べてしまうと実入りは微々たるものなんですが……。

 メモリーはここで探す、PC SHOP Ark

www.ark-pc.co.jp

 メモリー選びで個人的にオススメなサイトは、PC SHOP Arkの通販サイトです。

モリーは、ヒートシンクのカッコよさやレイテンシーなどの情報が重要ですが、価格.comではサムネイルが登録されてなかったり、レイテンシーが書いてなかったりと、探しにくい状態です。

PC SHOP Arkは、それらの情報に加え、メモリーに関する情報、品揃え、探しやすさがあり、見ているだけでも非常に楽しくなれるサイトです。

品揃えという点では、OVER CLOCK WORKSの通販サイトもおすすめです。

www.ocworks.com

 結構安い&ポイントがお得、EC-JOY

www.ecj.jp

 価格.comでも最安値が度々付いているEC-JOYですが、その真価はゲームポイントだと思っています。

1日1度、3分掛からずプレイできるゲームでポイントが獲得でき、自分の実例としては、1年7ヶ月で約1万ポイント(1ポイント=1円)、月500円以上のペースでポイントが溜まっていました。

先日レビューしたTt eSPORTS VENTUS Z RGB MO-VEZ-WDLOBK-01も、このポイントを利用して0円で手に入れたものです。

価格.comよりよっぽど時間効率が良いですね。

自作系パーツは豊富ですが、ここで一式揃えるのは厳しいので、そういう意味では周辺機器や、相性といった保証が絡まないものの購入にオススメなサイトです。

番外、Amazon.com(米尼)

www.amazon.com

番外編として、Amazon.comを紹介します。

代理店税や個人輸入などのキーワードでおなじみですね。

日本では高いパーツを安く買えたり、手に入らないパーツでも買える場合があるので、知っておいて損はないサイトです。

特にAmazon.comは購入の解説サイトも充実しており、トラブル対応が少し面倒という以外は、デメリットよりメリットのほうが大きいサイトです。

特に最近は価格差から、AMD製品の輸入が流行っている印象を受けています。

終わりに

個人的には、購入の際は、まず今挙げたようなサイトで探してから、CPU、マザー、メモリーに関しては一括で買える店で買うことをお勧めします。

TSUKUMOなんかは、通販でも店頭でも品揃えが良くて優秀ですね。

AndroidのOpenGL ESで、カメラからの入力の各画素を処理する

最近AndroidOpenGL ESを触っているので、少しだけ記事にしてみます。
多分タイトルは正確ではないんだろうなあ……。
OpenGL ESやGLSLに関しては全く詳しくないというか、自分のやりたいことはフラグメントシェーダを書くだけで実現できてしまったので、とりあえずその部分だけを記事にしています。

元にしたプロジェクト

今回のプロジェクトは、以下のプロジェクトをコピペして、OpenGL ESのバージョンを3.1に変え、フルスクリーン表示にしたものです。
qiita.com
カメラからの入力を受け取るための部分はこのプロジェクトのまんまです。

サンプルプロジェクト

全体は以下のGitHubリポジトリを参照して下さい。
ランタイムパーミッション関連を書いていないので、必要であればカメラパーミッションの設定をお願いします。
github.com

フラグメントシェーダ

OpenGL ESでは、GLSLで記述されたフラグメントシェーダが、各頂点の色に関する処理を行います。(今回は各頂点=各画素位のノリで書いていますが多分厳密には違う……)
今回はテストコードとして、画面の左半分であれば赤にノイズを掛け、青と緑を強める、という処理を実装してみました。
この内容はRenderer.java内に書いてあります。
今回は書いていませんが、行列演算も可能です。

#extension GL_OES_EGL_image_external : require
precision mediump float;
//texcoordVaryingには、テクスチャの0.0から1.0までの位置情報が格納されている
varying vec2 texcoordVarying;
uniform samplerExternalOES texture;

//https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
//0.0から1.0の一様乱数を返す関数、
//入力はその都度変わる何か、例えば色情報を用いる
float rand(vec2 co){
  return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n" +
}

//フラグメントシェーダのメイン関数
void main() {
  //色情報を取得, ここで取得されるのは0.0 〜 1.0の範囲の値を持つrgbaのベクトル
  vec4 v = texture2D(texture, texcoordVarying);
  //画面の左半分の場合処理する
  if(texcoordVarying.x < 0.5){
    //rに-0.5 〜 0.5の範囲の乱数を載せている
    //配列と同じようにアクセスできる
    v[0] += (rand(vec2(v[0] * v[1],v[0] * v[2])) - 0.5);
    //g, bを入力と1.0の平均で置き換える
    //このように、ベクトルはxyzw表記でアクセスしたり、ベクトルの一部を低次元のベクトルとして演算することが可能
    v.yz = vec2((v.y + 1.0)/2.0, (v.z + 1.0)/2.0);
  }
  gl_FragColor = v;
}
スクリーンショット

実行するとこんな感じになります。
f:id:wrongwrongwrongwrong163377:20170829185104p:plain

java上での取り扱い

上記のGLSLコードは、java内では、以下のようにStringで記述します。

    private static final String FRAGMENT_SHADER =
            "#extension GL_OES_EGL_image_external : require\n" +
                    "precision mediump float;\n" +
                    //texcoordVaryingには、テクスチャの0.0から1.0までの位置情報が格納されている
                    "varying vec2 texcoordVarying;\n" +
                    "uniform samplerExternalOES texture;\n" +

                    //https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
                    //0.0から1.0の一様乱数を返す関数、
                    //入力はその都度変わる何か、例えば色情報を用いる
                    "float rand(vec2 co){\n" +
                    "    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n" +
                    "}\n"+

                    //フラグメントシェーダのメイン関数
                    "void main() {\n" +
                    //色情報を取得, ここで取得されるのは0.0 〜 1.0の範囲の値を持つrgbaのベクトル
                    "  vec4 v = texture2D(texture, texcoordVarying);\n" +
                    //画面の左半分の場合処理する
                    "  if(texcoordVarying.x < 0.5){\n" +
                    //rに-0.5 〜 0.5の範囲の乱数を載せている
                    //配列と同じようにアクセスできる
                    "    v[0] += (rand(vec2(v[0] * v[1],v[0] * v[2])) - 0.5);\n" +
                    //g, bを入力と1.0の平均で置き換える
                    //このように、ベクトルはxyzw表記でアクセスしたり、ベクトルの一部を低次元のベクトルとして演算することが可能
                    "    v.yz = vec2((v.y + 1.0)/2.0, (v.z + 1.0)/2.0);\n"+
                    "  }\n"+
                    "  gl_FragColor = v;\n" +
                    "}\n";

余談

カメラ入力に対して各画素への処理を行いたい場合、例えばOpenCVを使うようなことが考えられますが、実際に比較してみると、OpenGL ESのを用いたほうがはるかに高速でした。
これは、画像処理をGPUで行うため計算が高速であることと、カメラから取り込んだデータを処理するまで、処理した後でデータ転送や変換が少ないことが原因でしょう。
勉強し始めたばかりなので分からないことだらけで、特にAndroid上での取り扱いに関しては資料が少なく、苦戦中です。。。

リンクスサポートセンターへの、Corsair製各種DDR4メモリーのヒートシンク高に関する問い合わせ

リンクス様のサポートセンターへ、Corsair製各種DDR4メモリーヒートシンク高に関して問い合わせを行いました。

問い合わせ内容の公開に関しては許可を頂いたため、記事として残します。

リンクス様、回答、並びに内容の公開をご承諾頂き、誠にありがとうございます。

頂いた情報に関しては、別記事に追記を行っています。

wrongwrong163377.hatenablog.com

wrongwrong163377.hatenablog.com

回答内容

以下、回答の内容です。

実測値にて最も高い部分でおおよそ

Dominator Platinum 55mm
Vengeance LED 49mm
Vengeance RGB 49mm
Vengeance LPX 34mm

となってります。ソースとしては
「代理店による実測値」
程度の記載でお願い致します。

Vengeance LPXは上部に突起がいくつもあり、また平らでなく外側にいくほど少し低くなっています。
もっとも高い部分を計測すると34mmですが、計測する箇所によって数字はばらつくと思われます。

各社で公開している数字につきましても、ヒートシンクがでこぼこしている場合、
もっとも高い部分を計っていない可能性もあり、また、ヒートシンク取り付け時の
わずかなズレ等もありますので、数字はあくまで目安であると考えます。

よろしくお願い致します。

 

MSI Fan Day開催記念企画、MSI Dragon-G Mini Seriesフィギュア、当たりました!

こちらのキャンペーンに応募していましたが、まさかの当選!開封しました!

何が届くか知らないまま待ってましたが、思ってたより大きな箱……。

f:id:wrongwrongwrongwrong163377:20170801132805j:plain

お?

f:id:wrongwrongwrongwrong163377:20170801132934j:plain

おおーっ!

f:id:wrongwrongwrongwrong163377:20170801132814j:plain

すごい!かっこいい!

f:id:wrongwrongwrongwrong163377:20170801132811j:plain

このページのドラゴンのフィギュア4種類でした!エフェクト付き!

jp.msi.com

なんかもう、かっこよすぎて中身取り出せなかったです^^;

MSI Dragon-G Mini Seriesというそうです。というかコレ、国内では手に入らないやつですよね。

しばらく自分だけで愛でたら、研究室に持っていって守護龍になってもらう予定です。

 MSIさん!本当にありがとうございました、こっちもワクワクしながら待ってます!

Androidで、JavaのActivityからc++のNativeActivityを呼び出す

Androidでは、c++のみで書かれるNativeActivityがあります。
github.com
これは通常のActivityと同じように、別のActivityから遷移させることが可能です。
今回は、この遷移についてやった内容を記事にしました。

サンプルプロジェクト

上のGoogleのサンプルのnative-activityサンプルを利用し、タッチイベントでNativeActivityに遷移を行うサンプルプロジェクトをGitHubに上げました。
github.com
これについて解説を行います。

プロジェクト作成

Include C++ supportにチェックを付けてプロジェクトを開始します。
NDKのインストールなどは、メッセージに従ってやって下さい。

NativeActivityを動かすための準備

今回は、先程貼ったGoogleのサンプルコードを、遷移先で動かそうと思います。
そのための準備を行っていきます。

main.cpp

Include C++ supportで自動生成されるnative-lib.cppは使わないので消します。
次に、プロジェクトのapp/src/main/cppフォルダに、サンプルプロジェクトのandroid-ndk/native-activity/app/src/main/cpp/main.cppを置きます。

CMakeLists.txtの編集

app/CMakeLists.txtの内容を、以下で置き換えます。

cmake_minimum_required(VERSION 3.4.1)

# build native_app_glue as a static lib
set(${CMAKE_C_FLAGS}, "${CMAKE_C_FLAGS}")
add_library(native_app_glue STATIC
    ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)

# now build app's shared lib
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall -Werror")

# Export ANativeActivity_onCreate(),
# Refer to: https://github.com/android-ndk/ndk/issues/381.
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")

add_library( native-activity SHARED src/main/cpp/main.cpp )

target_include_directories(native-activity PRIVATE ${ANDROID_NDK}/sources/android/native_app_glue)

find_library( log-lib log )

target_link_libraries( native-activity
                       android
                       native_app_glue
                       EGL
                       GLESv1_CM
                       ${log-lib} )

大概がサンプルからのコピペで、ソースのパス位しか変えていません。
注意点としては、ビルド後のコードはnative-activityとなっている点でしょうか。
後述するAndroidManifest.xmlと、MainActivityでのloadLibraryでは、この名前を指定します。

build.gradleの編集

app/build.gradleのexternNativeBuild内、cmakeの項目に、abiFiltersとargumentsの追記を行い、以下のようにします。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.wrongrong.changetonativeactivitysample"
        minSdkVersion 9
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
                arguments '-DANDROID_PLATFORM=android-9',
                        '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_static'
            }
        }
    }
︙

自動生成されるcmakeの項目にはcmakeのフラグについて記述(c++11を指定した場合、c++11に関する記述)がありますが、これは先程CMakeLists.txt内に記載を行ったので、消してしまって構いません。

AndroidManifest.xmlの編集

AndroidManifest.xmlの、application部に、activityに関して追記を行い、以下のようにします。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wrongrong.changetonativeactivitysample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Our activity is the built-in NativeActivity framework class.
     This will take care of integrating with our NDK code. -->
        <activity android:name="android.app.NativeActivity"
            android:label="@string/app_name"
            android:configChanges="orientation|keyboardHidden">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="native-activity" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
MainActivity.java

ここまで行った変更に合わせ、MainActivity.javaの内容を変更します。

public class MainActivity extends AppCompatActivity {
    static {
        System.loadLibrary("native-activity");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = (TextView) findViewById(R.id.sample_text);
    }

    //タップイベントで、nativeactivityに遷移する
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Intent intent[] = new Intent[1];
        intent[0] = new Intent(MainActivity.this, NativeActivity.class);
        startActivities(intent);

        return true;
    }
}

ここまで紹介した手順によって、NativeActivityに遷移することができます。

アクティビティの遷移は、以下のサイトを参考にさせていただきました。
akira-watson.com

終わりに

今回はNativeActivityへの遷移まで実践しました。
このような場合のActivity間のデータのやり取りはどのようにするのかはまだ検証していないので、検証したらいつか記事にするかもしれません。

javaで、if文と%(剰余)のどちらが速いかを少しだけ比較

以前c++で実験してみたif文と%(剰余)の比較をjavaでもやってみました。
wrongwrong163377.hatenablog.com

実行環境

実行環境は以下の通りです。

OS Windows10 Pro
CPU Core i7 6700
MEM DDR4 2133CL13 8GBx2
JDK 1.8.0_131

実行したコード

プロジェクト全体はGitHubに上げました。
github.com

public class Main {
    public static int MAX = 1000000000;

    public static int If(){
        int i = 0;
        int j = 0;

        long start = System.nanoTime();
        while(i < MAX) {
            if((j+=1) == 100) j = 0;
            i++;
        }
        long end = System.nanoTime();

        System.out.println("If  Time:" + (end - start) / 1000000f + "ms");

        return i + j;
    }

    public static int Mod(){
        int i = 0;
        int j = 0;

        long start = System.nanoTime();
        while(i < MAX){
            j = (j+1)%100;
            i++;
        }
        long end = System.nanoTime();

        System.out.println("Mod Time:" + (end - start) / 1000000f + "ms");

        return i + j;
    }

    public static void main(String[] args) {
        int Ifres = If();
        int Modres = Mod();

        System.out.println("If :" + Ifres + "\nMod:" + Modres);
    }
}

実行結果

実行結果は以下の通りです。
10回ほど実行して最速だったものを選びました。

Mod If
3383[ms] 249[ms]

感想

前回の結果からどちらが速いかという結果については予想できていましたが、c++に比べてjavaのifの結果が滅茶苦茶速いですね。
何回やっても結果はかなり安定していたので、計測ミスではないと思います。
Modに関しても、言うほど遅くはありません。
こうなってくると、以前やったAndroid上でのc++javaの速度比較の結果が何だったのか気になります。
wrongwrong163377.hatenablog.com
気になるけど検証する時間が……。

参考にしたサイト

時間計測はこちらのサイトを参考にさせて頂きました。
qiita.com