From f976d5ef644156ede5446b54a30b868a04b1e2a8 Mon Sep 17 00:00:00 2001 From: lltcggie Date: Wed, 8 Jun 2016 11:11:36 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E3=81=99=E3=82=8BGPU?= =?UTF-8?q?=E3=83=87=E3=83=90=E3=82=A4=E3=82=B9=E3=81=AE=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C=20#29?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/lang/english.json | 3 +- bin/lang/japanese.json | 3 +- common/waifu2x.cpp | 68 +++++++++++--- common/waifu2x.h | 4 +- waifu2x-caffe-gui/MainDialog.cpp | 147 ++++++++++++++++++++----------- waifu2x-caffe-gui/MainDialog.h | 12 +-- waifu2x-caffe-gui/Resource.rc | Bin 17346 -> 17726 bytes waifu2x-caffe-gui/resource.h | Bin 7798 -> 8074 bytes waifu2x-caffe/Source.cpp | 6 +- 9 files changed, 164 insertions(+), 79 deletions(-) diff --git a/bin/lang/english.json b/bin/lang/english.json index f807661..80dad86 100644 --- a/bin/lang/english.json +++ b/bin/lang/english.json @@ -90,5 +90,6 @@ "MessageNoOverwrite":"Already file exists in the destination: %s", "MessageCudaOldDeviceError":"Your CUDA device too old.\r\nPlease use Compute Capability 2.0 or more devices", "OK":"OK", -"Cancel":"Cancel" +"Cancel":"Cancel", +"IDC_STATIC_USE_GPU_NO":"Use GPU No" } diff --git a/bin/lang/japanese.json b/bin/lang/japanese.json index 4eabf45..2737b8f 100644 --- a/bin/lang/japanese.json +++ b/bin/lang/japanese.json @@ -90,5 +90,6 @@ "MessageNoOverwrite":"出力先に既にファイルが存在します: %s", "MessageCudaOldDeviceError":"CUDAデバイスが古いです。\r\nCompute Capability 2.0以上のデバイスを使用してください", "OK":"OK", -"Cancel":"キャンセル" +"Cancel":"キャンセル", +"IDC_STATIC_USE_GPU_NO":"使用GPU No" } diff --git a/common/waifu2x.cpp b/common/waifu2x.cpp index 27652f5..d5709bd 100644 --- a/common/waifu2x.cpp +++ b/common/waifu2x.cpp @@ -172,6 +172,41 @@ namespace }; IgnoreErrorCV g_IgnoreErrorCV; + + class CudaDeviceSet + { + private: + int orgDevice; + bool mIsSet; + + public: + CudaDeviceSet(const std::string &process, const int devno) : orgDevice(0), mIsSet(false) + { + if (process == "gpu" || process == "cudnn") + { + int count = 0; + if (cudaGetDeviceCount(&count) != CUDA_SUCCESS) + return; + + if (devno >= count || count < 0) + return; + + if (cudaGetDevice(&orgDevice) != CUDA_SUCCESS) + return; + + if (cudaSetDevice(devno) != CUDA_SUCCESS) + return; + + mIsSet = true; + } + } + + ~CudaDeviceSet() + { + if (mIsSet) + cudaSetDevice(orgDevice); + } + }; } template @@ -323,7 +358,7 @@ static Waifu2x::eWaifu2xError writeProtoBinary(const ::google::protobuf::Message } -Waifu2x::Waifu2x() : is_inited(false), isCuda(false), input_block(nullptr), dummy_data(nullptr), output_block(nullptr) +Waifu2x::Waifu2x() : is_inited(false), isCuda(false), input_block(nullptr), dummy_data(nullptr), output_block(nullptr), gpu_no(0) { } @@ -928,6 +963,8 @@ Waifu2x::eWaifu2xError Waifu2x::LoadParameterFromJson(boost::shared_ptr> net, cv::Mat &im) { + CudaDeviceSet devset(process, gpu_no); + const auto Height = im.size().height; const auto Width = im.size().width; const auto Line = im.step1(); @@ -1134,7 +1171,7 @@ Waifu2x::eWaifu2xError Waifu2x::ReconstructImage(boost::shared_ptr ScaleRatio, const boost::optional ScaleWidth, const boost::optional ScaleHeight, const boost::filesystem::path &ModelDir, const std::string &Process, - const boost::optional OutputQuality, const int OutputDepth, const bool UseTTA, const int CropSize, const int BatchSize) + const boost::optional OutputQuality, const int OutputDepth, const bool UseTTA, const int CropSize, const int BatchSize, const int GPUNo) { Waifu2x::eWaifu2xError ret; @@ -1175,6 +1212,7 @@ Waifu2x::eWaifu2xError Waifu2x::init(int argc, char** argv, const std::string &M crop_size = CropSize; batch_size = BatchSize; + gpu_no = GPUNo; inner_padding = layer_num; outer_padding = 1; @@ -1185,17 +1223,6 @@ Waifu2x::eWaifu2xError Waifu2x::init(int argc, char** argv, const std::string &M output_block_size = crop_size + (inner_padding + outer_padding - layer_num) * 2; - std::call_once(waifu2x_once_flag, [argc, argv]() - { - assert(argc >= 1); - - int tmpargc = 1; - char* tmpargvv[] = { argv[0] }; - char** tmpargv = tmpargvv; - // glog̏ - caffe::GlobalInit(&tmpargc, &tmpargv); - }); - const auto cuDNNCheckStartTime = std::chrono::system_clock::now(); if (process == "gpu") @@ -1209,6 +1236,19 @@ Waifu2x::eWaifu2xError Waifu2x::init(int argc, char** argv, const std::string &M const auto cuDNNCheckEndTime = std::chrono::system_clock::now(); + CudaDeviceSet devset(process, gpu_no); + + std::call_once(waifu2x_once_flag, [argc, argv]() + { + assert(argc >= 1); + + int tmpargc = 1; + char* tmpargvv[] = { argv[0] }; + char** tmpargv = tmpargvv; + // glog̏ + caffe::GlobalInit(&tmpargc, &tmpargv); + }); + boost::filesystem::path mode_dir_path(model_dir); if (!mode_dir_path.is_absolute()) // model_dir΃pXȂ΃pXɒ { @@ -1287,6 +1327,8 @@ Waifu2x::eWaifu2xError Waifu2x::init(int argc, char** argv, const std::string &M void Waifu2x::destroy() { + CudaDeviceSet devset(process, gpu_no); + net_noise.reset(); net_scale.reset(); diff --git a/common/waifu2x.h b/common/waifu2x.h index b7569c7..999fa41 100644 --- a/common/waifu2x.h +++ b/common/waifu2x.h @@ -117,6 +117,8 @@ private: boost::optional output_quality; int output_depth; + int gpu_no; + private: static eWaifu2xError LoadMat(cv::Mat &float_image, const boost::filesystem::path &input_file); static eWaifu2xError LoadMatBySTBI(cv::Mat &float_image, const std::vector &img_data); @@ -162,7 +164,7 @@ public: const boost::optional scale_ratio, const boost::optional scale_width, const boost::optional scale_height, const boost::filesystem::path &model_dir, const std::string &process, const boost::optional output_quality = boost::optional(), const int output_depth = 8, const bool use_tta = false, - const int crop_size = 128, const int batch_size = 1); + const int crop_size = 128, const int batch_size = 1, const int gpu_no = 0); void destroy(); diff --git a/waifu2x-caffe-gui/MainDialog.cpp b/waifu2x-caffe-gui/MainDialog.cpp index 55abccb..57de429 100644 --- a/waifu2x-caffe-gui/MainDialog.cpp +++ b/waifu2x-caffe-gui/MainDialog.cpp @@ -36,68 +36,81 @@ const TCHAR * const MultiFileStr = TEXT("(Multi File)"); const UINT_PTR nIDEventTimeLeft = 1000; -// http://stackoverflow.com/questions/10167382/boostfilesystem-get-relative-path -boost::filesystem::path relativePath(const boost::filesystem::path &path, const boost::filesystem::path &relative_to) +namespace { - // create absolute paths - boost::filesystem::path p = boost::filesystem::absolute(path); - boost::filesystem::path r = boost::filesystem::absolute(relative_to); - - // if root paths are different, return absolute path - if (p.root_path() != r.root_path()) - return p; - - // initialize relative path - boost::filesystem::path result; - - // find out where the two paths diverge - boost::filesystem::path::const_iterator itr_path = p.begin(); - boost::filesystem::path::const_iterator itr_relative_to = r.begin(); - while (*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end()) + template + static tstring to_tstring(T val) { - ++itr_path; - ++itr_relative_to; +#ifdef UNICODE + return std::to_wstring(val); +#else + return std::to_string(val); +#endif } - // add "../" for each remaining token in relative_to - if (itr_relative_to != r.end()) + // http://stackoverflow.com/questions/10167382/boostfilesystem-get-relative-path + boost::filesystem::path relativePath(const boost::filesystem::path &path, const boost::filesystem::path &relative_to) { - ++itr_relative_to; - while (itr_relative_to != r.end()) + // create absolute paths + boost::filesystem::path p = boost::filesystem::absolute(path); + boost::filesystem::path r = boost::filesystem::absolute(relative_to); + + // if root paths are different, return absolute path + if (p.root_path() != r.root_path()) + return p; + + // initialize relative path + boost::filesystem::path result; + + // find out where the two paths diverge + boost::filesystem::path::const_iterator itr_path = p.begin(); + boost::filesystem::path::const_iterator itr_relative_to = r.begin(); + while (*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end()) { - result /= ".."; + ++itr_path; ++itr_relative_to; } + + // add "../" for each remaining token in relative_to + if (itr_relative_to != r.end()) + { + ++itr_relative_to; + while (itr_relative_to != r.end()) + { + result /= ".."; + ++itr_relative_to; + } + } + + // add remaining path + while (itr_path != p.end()) + { + result /= *itr_path; + ++itr_path; + } + + return result; } - // add remaining path - while (itr_path != p.end()) + std::vector CommonDivisorList(const int N) { - result /= *itr_path; - ++itr_path; + std::vector list; + + const int sq = sqrt(N); + for (int i = 1; i <= sq; i++) + { + if (N % i == 0) + list.push_back(i); + } + + const int sqs = list.size(); + for (int i = 0; i < sqs; i++) + list.push_back(N / list[i]); + + std::sort(list.begin(), list.end()); + + return list; } - - return result; -} - -std::vector CommonDivisorList(const int N) -{ - std::vector list; - - const int sq = sqrt(N); - for (int i = 1; i <= sq; i++) - { - if (N % i == 0) - list.push_back(i); - } - - const int sqs = list.size(); - for (int i = 0; i < sqs; i++) - list.push_back(N / list[i]); - - std::sort(list.begin(), list.end()); - - return list; } @@ -675,7 +688,7 @@ void DialogEvent::ProcessWaifu2x() } Waifu2x w; - ret = w.init(__argc, __argv, mode, noise_level, ScaleRatio, ScaleWidth, ScaleHeight, model_dir, process, output_quality, output_depth, use_tta, crop_size, batch_size); + ret = w.init(__argc, __argv, mode, noise_level, ScaleRatio, ScaleWidth, ScaleHeight, model_dir, process, output_quality, output_depth, use_tta, crop_size, batch_size, gpu_no); if (ret != Waifu2x::eWaifu2xError_OK) SendMessage(dh, WM_ON_WAIFU2X_ERROR, (WPARAM)&ret, 0); else @@ -924,6 +937,8 @@ void DialogEvent::SaveIni(const bool isSyncMember) WritePrivateProfileString(TEXT("Setting"), TEXT("LastUseTTA"), to_tstring(use_tta ? 1 : 0).c_str(), getTString(SettingFilePath).c_str()); + WritePrivateProfileString(TEXT("Setting"), TEXT("LastDeviceNo"), to_tstring(gpu_no).c_str(), getTString(SettingFilePath).c_str()); + if (output_quality) WritePrivateProfileString(TEXT("Setting"), TEXT("LastOutputQuality"), boost::lexical_cast(*output_quality).c_str(), getTString(SettingFilePath).c_str()); else @@ -1130,7 +1145,7 @@ UINT_PTR DialogEvent::OFNHookProcOut(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARA DialogEvent::DialogEvent() : dh(nullptr), mode("noise_scale"), noise_level(1), scale_ratio(2.0), scale_width(0), scale_height(0), model_dir(TEXT("models/anime_style_art_rgb")), process("gpu"), outputExt(TEXT(".png")), inputFileExt(TEXT("png:jpg:jpeg:tif:tiff:bmp:tga")), -use_tta(false), output_depth(8), crop_size(128), batch_size(1), isLastError(false), scaleType(eScaleTypeEnd), +use_tta(false), output_depth(8), crop_size(128), batch_size(1), gpu_no(0), isLastError(false), scaleType(eScaleTypeEnd), TimeLeftThread(-1), TimeLeftGetTimeThread(0), isCommandLineStart(false), tAutoMode(TEXT("none")), isArgStartAuto(true), isArgStartSuccessFinish(true), isOutputNoOverwrite(false), isNotSaveParam(false) {} @@ -1650,6 +1665,8 @@ void DialogEvent::Create(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) use_tta = GetPrivateProfileInt(TEXT("Setting"), TEXT("LastUseTTA"), 0, getTString(SettingFilePath).c_str()) != 0; + gpu_no = GetPrivateProfileInt(TEXT("Setting"), TEXT("LastDeviceNo"), 0, getTString(SettingFilePath).c_str()); + output_quality.reset(); const int num = GetPrivateProfileInt(TEXT("Setting"), TEXT("LastOutputQuality"), -100, getTString(SettingFilePath).c_str()); if (num != -100) @@ -1920,6 +1937,10 @@ void DialogEvent::Create(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) L"input batch size", false, 1, L"int", cmd); + TCLAP::ValueArg cmdGPUNoFile(L"", L"gpu", + L"gpu device no", false, + 0, L"int", cmd); + std::vector cmdBoolConstraintV; cmdBoolConstraintV.push_back(0); cmdBoolConstraintV.push_back(1); @@ -2134,6 +2155,13 @@ void DialogEvent::Create(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) isSetParam = true; } + if (cmdGPUNoFile.isSet()) + { + gpu_no = cmdGPUNoFile.getValue(); + + isSetParam = true; + } + if (cmdTTA.isSet()) { SendMessage(GetDlgItem(dh, IDC_CHECK_TTA), BM_SETCHECK, cmdTTA.getValue() ? BST_CHECKED : BST_UNCHECKED, 0); @@ -2844,6 +2872,7 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD bool isOutputNoOverwrite; tstring tInputDirFix; tstring tOutputDirFix; + int gpu_no; private: void AppSettingDialogEvent::SetWindowTextLang() @@ -2872,6 +2901,8 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD SET_WINDOW_TEXT(IDC_CHECK_OUTPUT_NO_OVERWIRITE); + SET_WINDOW_TEXT(IDC_STATIC_USE_GPU_NO); + #undef SET_WINDOW_TEXT } @@ -2926,6 +2957,8 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD SetWindowText(GetDlgItem(hWnd, IDC_EDIT_INPUT_DIR_FIX), tInputDirFix.c_str()); SetWindowText(GetDlgItem(hWnd, IDC_EDIT_OUTPUT_DIR_FIX), tOutputDirFix.c_str()); + + SetWindowText(GetDlgItem(hWnd, IDC_EDIT_USE_GPU_NO), to_tstring(gpu_no).c_str()); } void Close(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) @@ -2935,6 +2968,8 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD void sync() { + TCHAR *ptr = nullptr; + if (SendMessage(GetDlgItem(dh, IDC_RADIO_AUTO_START_ONE), BM_GETCHECK, 0, 0)) tAutoMode = TEXT("one"); else if (SendMessage(GetDlgItem(dh, IDC_RADIO_AUTO_START_MULTI), BM_GETCHECK, 0, 0)) @@ -2960,6 +2995,12 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD GetWindowText(GetDlgItem(dh, IDC_EDIT_OUTPUT_DIR_FIX), buf, _countof(buf)); buf[_countof(buf) - 1] = TEXT('\0'); tOutputDirFix = buf; + + GetWindowText(GetDlgItem(dh, IDC_EDIT_USE_GPU_NO), buf, _countof(buf)); + buf[_countof(buf) - 1] = TEXT('\0'); + const auto devno = _tcstol(buf, &ptr, 10); + if ((!ptr || *ptr == TEXT('\0')) && devno >= 0) + gpu_no = devno; } void AppSettingDialogEvent::OK(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) @@ -2983,6 +3024,7 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD cAppSettingDialogEvent.isOutputNoOverwrite = isOutputNoOverwrite; cAppSettingDialogEvent.tInputDirFix = tInputDirFix; cAppSettingDialogEvent.tOutputDirFix = tOutputDirFix; + cAppSettingDialogEvent.gpu_no = gpu_no; CDialog cDialog; @@ -3003,6 +3045,7 @@ void DialogEvent::AppSetting(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpD isOutputNoOverwrite = cAppSettingDialogEvent.isOutputNoOverwrite; tInputDirFix = cAppSettingDialogEvent.tInputDirFix; tOutputDirFix = cAppSettingDialogEvent.tOutputDirFix; + gpu_no = cAppSettingDialogEvent.gpu_no; if (tOutputDirFix.length() > 0 && boost::filesystem::exists(tOutputDirFix)) { diff --git a/waifu2x-caffe-gui/MainDialog.h b/waifu2x-caffe-gui/MainDialog.h index 48c2a31..db2f685 100644 --- a/waifu2x-caffe-gui/MainDialog.h +++ b/waifu2x-caffe-gui/MainDialog.h @@ -51,6 +51,8 @@ private: int crop_size; int batch_size; + int gpu_no; + std::vector extList; std::thread processThread; @@ -107,16 +109,6 @@ private: bool isNotSaveParam; private: - template - static tstring to_tstring(T val) - { -#ifdef UNICODE - return std::to_wstring(val); -#else - return std::to_string(val); -#endif - } - tstring AddName() const; bool SyncMember(const bool NotSyncCropSize, const bool silent = false); diff --git a/waifu2x-caffe-gui/Resource.rc b/waifu2x-caffe-gui/Resource.rc index 12ebd8b9eddc21ecf9c6f5cb239db91961c882b4..5a3615ca8d6923a4eff3da26486e89dd31a94fd1 100644 GIT binary patch delta 180 zcmX@q&bY6OaYL0Mqxt4)!?i4v|Cw-1o@J`UU+=F`>dp|r5Xzvy;Kz_Zc_N>*dMHCM zgDXQk14KL?DDKao!(a}?mJB99(uBbfNLoyO$Y-yLU9A~|F<3Q7oe6`%WJeR#$^T^7 sCZCgM|BnM>gTjW@b(t%oaf78m+XMEg|&g3Og@W04aYd3IG5A delta 34 qcmdnj#dxTlaYL0Mqs8WG!?i4vzp?R6j&azqnayGn`{pn9UaSD}hYfQ8 diff --git a/waifu2x-caffe-gui/resource.h b/waifu2x-caffe-gui/resource.h index 879a6f3f5ed1cdc29c7519483420dedc6f7abf03..a7d2d0e6ed02892ab911386e1c56eaef8ed2142b 100644 GIT binary patch delta 110 zcmexn(`COwNM>@Bw8Ufw0Y2eShF}I)hIj^dh5&|8AnnKCKbet9dh!=piOB&R0*oe; t6FH2T%@~X(2MWnfe!$3uRmVa`d61gTyfQBtCtu7y!yR8s`82 delta 20 bcmeCO|7Np6NM^H|>=VYx88Tv%738x3Q&0yU diff --git a/waifu2x-caffe/Source.cpp b/waifu2x-caffe/Source.cpp index d65b250..535a9e8 100644 --- a/waifu2x-caffe/Source.cpp +++ b/waifu2x-caffe/Source.cpp @@ -135,6 +135,10 @@ int main(int argc, char** argv) "input batch size", false, 1, "int", cmd); + TCLAP::ValueArg cmdGPUNoFile("", "gpu", + "gpu device no", false, + 0, "int", cmd); + std::vector cmdTTAConstraintV; cmdTTAConstraintV.push_back(0); cmdTTAConstraintV.push_back(1); @@ -319,7 +323,7 @@ int main(int argc, char** argv) Waifu2x w; ret = w.init(argc, argv, cmdMode.getValue(), cmdNRLevel.getValue(), ScaleRatio, ScaleWidth, ScaleHeight, cmdModelPath.getValue(), cmdProcess.getValue(), cmdOutputQuality.getValue() == -1 ? boost::optional() : cmdOutputQuality.getValue(), cmdOutputDepth.getValue(), use_tta, cmdCropSizeFile.getValue(), - cmdBatchSizeFile.getValue()); + cmdBatchSizeFile.getValue(), cmdGPUNoFile.getValue()); switch (ret) { case Waifu2x::eWaifu2xError_InvalidParameter: