物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

Pocoによる共有メモリの書き込み・読み出しの実装例

Pocoはc++のライブラリの一つで、boostより比較的軽量に設計されている。バージョン1.7.3を使って共有メモリの書き込み・読み出しの実装例を書いた。 読み出しでもAM_WRITEになっているのは読み出しで先にOPENしてしまうと書き込みのほうで例外が投げられるため。

for文はrange-based for loopsを使った。

読み出し

#include <iostream>
#include <Poco/SharedMemory.h>
#include <Poco/Thread.h>

int main() {
    size_t size = 10;
    auto sm = Poco::SharedMemory("phst_test", size, Poco::SharedMemory::AccessMode::AM_WRITE);

    while (true) {
        Poco::Thread::sleep(1000);
        for (const auto &p : sm) { //const auto &
            std::cout << int(p) << " "; //読み出し
        }
        std::cout<<std::endl;
    }
    
}

書き込み

#include <iostream>
#include <Poco/SharedMemory.h>
#include <Poco/Thread.h>

int main() {
    size_t size = 10;
    auto sm = Poco::SharedMemory("phst_test", size, Poco::SharedMemory::AccessMode::AM_WRITE);

    char c = 0;
    while (true) {
        Poco::Thread::sleep(1000);
        std::cout << int(c) << std::endl;
        for (auto &&p : sm) { //auto &&
            p = c; //書き込み
        }
        c++;
    }

}

参照

qiita.com

PocoによるTCP/IP通信のサーバー・クライアント実装例

Pocoはc++のライブラリの一つで、boostより比較的軽量に設計されている。バージョン1.7.3を使ってTCP通信のサーバー・クライアントの実装例を書いた。例外処理は甘いところがあるので適宜変更されたし。

サーバーの実装例

#include <iostream>

#include <Poco/Net/Socket.h>
#include <Poco/Net/TCPServer.h>
#include <Poco/Net/StreamSocket.h>

const int BYTE_LENGTH = 1024;

void tcp_send(Poco::Net::StreamSocket &ss, std::string str)
{
    if (str.size() > BYTE_LENGTH) throw std::invalid_argument("str.size() > BYTE_LENGTH");
    int ret = ss.sendBytes(str.c_str(), str.size());
    if (ret < 0) throw std::exception();
}
std::string tcp_read(Poco::Net::StreamSocket &ss)
{
    char data[BYTE_LENGTH];
    int count = ss.receiveBytes(data, BYTE_LENGTH);
    std::string str(data, count);
    if (count == BYTE_LENGTH) throw std::exception();
    return str;
}

int main() {
    int port = 15001;

    while (true) {
        Poco::Net::ServerSocket *serv;
        Poco::Net::StreamSocket *ss;
        serv = new Poco::Net::ServerSocket(port);
        serv->listen();

        std::cout << "Waiting for connection";
        ss = new Poco::Net::StreamSocket(serv->acceptConnection());
        ss->setNoDelay(true);
        std::cout << "\rConnected from " << ss->peerAddress().host().toString() << " " << ss->address().port() << std::endl;
        try {
            while (true) {
                std::string str = tcp_read(*ss);
                tcp_send(*ss, "You sent " + str);
                std::cout << "I received \"" + str << "\"." << std::endl;
            }
        }
        catch (...) {
            ss->close();
            serv->close();
        }
    }
}

クライアントの実装例

#include <iostream>

#include <Poco/Net/Socket.h>
#include <Poco/Net/StreamSocket.h>
#include <Poco/Thread.h>

const int BYTE_LENGTH = 1024;

void tcp_send(Poco::Net::StreamSocket &ss, std::string str)
{
    if (str.size() > BYTE_LENGTH) throw std::invalid_argument("str.size() > BYTE_LENGTH");
    int ret = ss.sendBytes(str.c_str(), str.size());
    if (ret < 0) throw std::exception();
}
std::string tcp_read(Poco::Net::StreamSocket &ss)
{
    char data[BYTE_LENGTH];
    int count = ss.receiveBytes(data, BYTE_LENGTH);
    std::string str(data, count);
    if (count == BYTE_LENGTH) throw std::exception();
    return str;
}

int main() {
    int port = 15001;
    std::string host = "localhost";

    while (true) {
        try {
            Poco::Net::StreamSocket *ss;
            auto address = Poco::Net::SocketAddress(host, port);
            ss = new Poco::Net::StreamSocket(address.family());
            ss->setNoDelay(true);
            ss->connect(address);
            try {

                while (true) {
                    std::string str;
                    std::cin >> str;
                    tcp_send(*ss, str);
                    std::cout << "I received \"" + tcp_read(*ss) << "\"."<< std::endl;
                }
            }
            catch (...) {
                ss->close();
            }
        }
        catch (...) {
            Poco::Thread::sleep(1000);
            std::cout << "Waiting for server to startup\n";
        }
    }
}

PsExec でパイプの他端にプロセスがありません。と出るエラーへの対処

Error communicating with PsExec service on ****:
パイプの他端にプロセスがありません。

というエラーが出たので、次のフォーラムの記述を参考に対処したメモ

Windows タスクマネージャーから、全ユーザーのプロセスを表示して、PSEXESVC.exeのプロセスを終了→再接続。

これだけ。

forum.sysinternals.com

PsExecのコマンドを送りすぎが原因という噂もあるが、良く分からない。

OpenCVのgpu::countNonZeroをgpu::Streamで高速化する

cv::gpu::countNonZerogpu::Streamで高速化したいという需要があったので、その解決策を書いておく。

opencvの2系のcountNonZeroはstreamを使うことが出来ない。そのため、非同期処理を行い高速化する際のボトルネックになる。cv::gpu::reduceは2次元画像を1次元に射影するための関数でstreamが使えるので、CV_REDUCE_SUMを使って射影した後、軽量化された1次元画像を非同期ダウンロードし、CPUで積算処理を行えばよい。行または列の合計値が255を超えた場合は完全に一致しないものの、ラフな値で良い場合はこの方法が適切である。

以下はサンプルコードでは、コアの部分だけ記述した。streamやgvec等を使いまわさないと初期化に時間がかかるので注意が必要。

cv::gpu::GpuMat gmat = cv::gpu::GpuMat(cv::Size(1920, 1080), CV_8UC1);
cout << cv::gpu::countNonZero(gmat) << endl; //streamが使えない

cv::gpu::GpuMat gvec;
cv::gpu::Stream stream;
cv::gpu::reduce(gmat, gvec, 1, CV_REDUCE_SUM, -1, stream); //行ごとに積算する場合
cv::Mat vec;
stream.enqueueDownload(gvec, vec);
cout << cv::sum(vec)[0] << endl;

C# でWindows 上のプログラムのリソースを監視する

C#で以下のリソースの監視をしたいという需要があったのでサンプルコードを公開する。

  • 使用メモリ量
  • ハンドル数
  • GDI オブジェクト数
  • User オブジェクト数
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport("user32.dll")]
        private static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags);
        const uint GR_GDIOBJECTS = 0;
        const uint GR_USEROBJECTS = 1;
        /// <summary>
        /// GDI オブジェクトの数を返す
        /// </summary>
        /// <returns></returns>
        public static uint GetGDIObjects()
        {
            return GetGuiResources(Process.GetCurrentProcess().Handle, GR_GDIOBJECTS);
        }
        /// <summary>
        /// User オブジェクトの数を返す
        /// </summary>
        /// <returns></returns>
        public static uint GetUserObjects()
        {
            return GetGuiResources(Process.GetCurrentProcess().Handle, GR_USEROBJECTS);
        }
        static void DisplayMemory()
        {
            Console.WriteLine("Total memory  : {0:###,###,###,##0} bytes", GC.GetTotalMemory(false));
            Console.WriteLine("Private bytes   {0:###,###,###,##0} bytes", Process.GetCurrentProcess().PrivateMemorySize64); //プライベート メモリの量
            Console.WriteLine("Handle   count: {0}", Process.GetCurrentProcess().HandleCount); // ハンドル数
            Console.WriteLine("GDI  obj count: {0}", GetGDIObjects());
            Console.WriteLine("User obj count: {0}", GetUserObjects());
            Console.WriteLine();
        }
        static void Main(string[] args)
        {
            for (int i = 0; i < 100; i++)
            {
                using (var p = new Process())
                {
                    p.StartInfo.FileName = "ipconfig";
                    p.Start();
                    p.WaitForExit();
                }
            }
            DisplayMemory();
            GC.Collect(); //ガーベッジ コレクションを行う
            GC.WaitForPendingFinalizers(); //ガーベッジ コレクションが終わるまで待つ
            DisplayMemory();
        }
    }
}

標準出力とタスクマネージャーはこんな感じ

f:id:onsanai:20161004160344p:plain:w600

参照

.net - Finding Memory leaks in C# - Stack Overflow

GDI object count - C# / C Sharp