目次: Linux
Debian Testingのapt-get updateをしたら、xrdp経由で起動しているX.orgがエラーで起動しなくなりました。こんなエラーが出ています。
[  1416.016] (EE)
[  1416.016] (EE) Backtrace:
[  1416.016] (EE) 0: /usr/lib/xorg/Xorg (OsLookupColor+0x14d) [0x556fb13c8dad]
[  1416.017] (EE) 1: /lib/x86_64-linux-gnu/libc.so.6 (__sigaction+0x40) [0x7f084f9dad20]
[  1416.017] (EE) 2: /lib/x86_64-linux-gnu/libc.so.6 (pthread_key_delete+0x14c) [0x7f084fa2ee5c]
[  1416.017] (EE) 3: /lib/x86_64-linux-gnu/libc.so.6 (gsignal+0x12) [0x7f084f9dac82]
[  1416.018] (EE) 4: /lib/x86_64-linux-gnu/libc.so.6 (abort+0xd3) [0x7f084f9c34f0]
[  1416.018] (EE) 5: /lib/x86_64-linux-gnu/libc.so.6 (perror+0xcb7) [0x7f084f9c432d]
[  1416.018] (EE) 6: /lib/x86_64-linux-gnu/libc.so.6 (timer_settime+0x395) [0x7f084fa389e5]
[  1416.019] (EE) 7: /lib/x86_64-linux-gnu/libc.so.6 (timer_settime+0x59c) [0x7f084fa38bec]
[  1416.019] (EE) 8: /lib/x86_64-linux-gnu/libc.so.6 (__libc_free+0xb8) [0x7f084fa3d548]
[  1416.019] (EE) 9: /lib/x86_64-linux-gnu/libdrm.so.2 (drmFreeDevice+0x7d) [0x7f084febf13d]
[  1416.020] (EE) 10: /lib/x86_64-linux-gnu/libdrm.so.2 (drmFreeDevices+0x2e) [0x7f084febf2ae]
[  1416.020] (EE) 11: /lib/x86_64-linux-gnu/libnvidia-egl-gbm.so.1 (loadEGLExternalPlatform+0x8a8) [0x7f084477dd18]
[  1416.020] (EE) 12: /lib/x86_64-linux-gnu/libEGL_nvidia.so.0 (NvEglwlaf47906in+0x6e240) [0x7f08404ad480]
[  1416.020] (EE) 13: /lib/x86_64-linux-gnu/libEGL_nvidia.so.0 (NvEglwlaf47906in+0xd73c) [0x7f084044c97c]
[  1416.020] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.020] (EE) 14: /lib/x86_64-linux-gnu/libEGL.so.1 (?+0x0) [0x7f0844a6ead5]
[  1416.020] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.020] (EE) 15: /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so (?+0x0) [0x7f0844aaf3f3]
[  1416.021] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.021] (EE) 16: /usr/lib/xorg/modules/extensions/libglx.so (?+0x0) [0x7f084f65cbe3]
[  1416.021] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  1416.021] (EE) 17: /usr/lib/xorg/modules/extensions/libglx.so (?+0x0) [0x7f084f65ba1f]
[  1416.021] (EE) 18: /usr/lib/xorg/Xorg (_CallCallbacks+0x3c) [0x556fb125002c]
[  1416.021] (EE) 19: /usr/lib/xorg/Xorg (dri3_send_open_reply+0x111f) [0x556fb138334f]
[  1416.021] (EE) 20: /usr/lib/xorg/Xorg (InitExtensions+0x89) [0x556fb12bde29]
[  1416.021] (EE) 21: /usr/lib/xorg/Xorg (InitFonts+0x1f8) [0x556fb124e968]
[  1416.022] (EE) 22: /lib/x86_64-linux-gnu/libc.so.6 (__libc_init_first+0x88) [0x7f084f9c4d68]
[  1416.022] (EE) 23: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0x85) [0x7f084f9c4e25]
[  1416.022] (EE) 24: /usr/lib/xorg/Xorg (_start+0x21) [0x556fb12373f1]
[  1416.022] (EE)
[  1416.022] (EE)
Fatal server error:
[  1416.022] (EE) Caught signal 6 (Aborted). Server aborting
[  1416.022] (EE)
[  1416.022] (EE)
Please consult the The X.Org Foundation support
         at http://wiki.x.org
 for help.
[  1416.022] (EE) Please also check the log file at ".xorgxrdp.10.log" for additional information.
[  1416.022] (EE)
[  1416.022] rdpLeaveVT:
[  1416.022] (EE) Server terminated with error (1). Closing log file.
エラーの原因であるlibEGL_nvidia.soを削除すれば起動しそうだったので、libegl-nvidia0パッケージを消したところX.orgが起動しました。めでたしめでたし……ではありません。どうしてこうなった?
他にも何か起きているだろうか?と調べたらCUDAが使えないし、nvidia-smiがデバイスがないと言っています。NVIDIA系の機能が全滅です。どうやらnvidia.koが消滅していて、GPUカードが認識されなくなったようです。NVIDIAドライバパッケージを再インストールするとこんなメッセージが出ました。
nvidia-kernel-dkms (535.216.03-1) を設定しています ... Loading new nvidia-current-535.216.03 DKMS files... Building for 6.11.10-amd64 Module build for kernel 6.11.10-amd64 was skipped since the kernel headers for this kernel do not seem to be installed.
メッセージはカーネルヘッダをインストールしないとカーネルモジュールがビルドされないとおっしゃっています。カーネルヘッダパッケージlinux-headers-6.11.10-amd64をインストールしたところ無事/lib/modules/6.11.10-amd64/updates/dkms/の下にnvidia-current.ko.xzが生成され、CUDAが復活しました。めでたしめでたし……じゃないんだ、まだ。
X.orgは/dev/driの下にあるデバイスファイルにアクセスするので、DRM関連のドライバも必要です。DRM用のドライバパッケージをインストールするとnvidia-current-drm.ko.xzが生成されます。たしかパッケージ名はnvidia-vdpau-driverだったと思います。
カーネルモジュールが生成されたらmodprobe nvidia-drmでロードすれば/dev/dri/card0が出現します。先ほど削除したlibegl-nvidia0パッケージを再インストールしてもX.orgの起動に失敗しなくなりました。めでたしめでたし。
とはいえxrdp経由で起動していると、DRMが有効でも"unsupported render mode"と言われてしまってHWアクセラレーションが効いてなさそうに見えます。せっかく直したのに悲しいですね……。
 この記事にコメントする
 この記事にコメントする
PCは起動時にあるキーを押すとBIOS/UEFIの設定画面に遷移します。良く見るパターンはF1, F2, DELキー辺りですが、メーカーごとに完全にバラバラで統一感なしです。私の場合、初めて見るPCのBIOS/UEFI画面を拝みたいときはEsc, F1, F2, F12, DEL辺りを乱打しながら起動します。これでもたまに普通に起動してしまうPCがあってイライラします。
Twitterでこの話に言及したら、いくつか知らないパターンを教えてもらいましたのでそれも紹介します。
こんなものに独自性を出して誰が幸せになるんでしょうか?実に不毛です。PCメーカーとBIOSメーカーはさっさとキーを統一してください……。
 この記事にコメントする
 この記事にコメントする
目次: Linux
高速なJPEGデコード/エンコードライブラリで有名なlibjpeg-turboですが、ライブラリというかAPIが2系統あります(公式ドキュメントへのリンク、libjpeg-turboのソースコード)。系統その1はlibjpeg(IJG: Independent JPEG Groupのライブラリ)互換のAPIで、系統その2は独自のTurboJPEG APIです。パッケージの名前もややこしくて、しばらくしたら忘れてしまいそうなのでメモしておきます。
各パッケージに含まれるファイルも示しておきます。
libjpeg-turbo8 /usr/lib/aarch64-linux-gnu/libjpeg.so.8 /usr/lib/aarch64-linux-gnu/libjpeg.so.8.2.2 libjpeg-turbo8-dev /usr/include/aarch64-linux-gnu/jconfig.h /usr/include/jerror.h /usr/include/jmorecfg.h /usr/include/jpegint.h /usr/include/jpeglib.h /usr/lib/aarch64-linux-gnu/libjpeg.a /usr/lib/aarch64-linux-gnu/libjpeg.so /usr/lib/aarch64-linux-gnu/pkgconfig/libjpeg.pc libturbojpeg /usr/lib/aarch64-linux-gnu/libturbojpeg.so.0 /usr/lib/aarch64-linux-gnu/libturbojpeg.so.0.2.0 libturbojpeg0-dev /usr/include/turbojpeg.h /usr/lib/aarch64-linux-gnu/libturbojpeg.a /usr/lib/aarch64-linux-gnu/libturbojpeg.so /usr/lib/aarch64-linux-gnu/pkgconfig/libturbojpeg.pc
例としてUbuntu 22.04 AArch64向けのものを示しましたが、他のアーキテクチャやバージョンでも構造は同じです。
 この記事にコメントする
 この記事にコメントする
目次: Linux
半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。NVIDIA GPUとCUDAを使ってJPEGが扱えるそうで、API名はnvJPEGだそうです(nvJPEGのAPIドキュメント)。
前回まではデコード処理でした。今回はエンコードのAPIをご紹介します。decoupled decodingのような複雑なAPIは存在しないようです。
Raw YUV420の画素データを置くメモリを確保する際はcudaMalloc()ではなく、cudaMallocHost()を使う点がデコードと異なります。エンコードはこんな感じでした。
	cudaStream_t stream = nullptr;
	nvjpegHandle_t nvj_handle = nullptr;
	nvjpegEncoderState_t nvj_state = nullptr;
	nvjpegEncoderParams_t nvj_param = nullptr;
	nvjpegImage_t inbuf = {0};
	uint8_t *jpegbuf = nullptr;
	size_t bufsize = 0;
	int r;
	// Create
	cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
	nvjpegCreateEx(NVJPEG_BACKEND_DEFAULT, nullptr, nullptr, NVJPEG_FLAGS_DEFAULT, &nvj_handle);
	nvjpegEncoderStateCreate(nvj_handle, &nvj_state, stream);
	nvjpegEncoderParamsCreate(nvj_handle, &nvj_param, stream);
	// Set JPEG parameters
	nvjpegEncoderParamsSetQuality(nvj_param, 80, stream);
	nvjpegEncoderParamsSetSamplingFactors(nvj_param, NVJPEG_CSS_420, stream);
	// 2のべき乗境界に切り上げる
#define ALIGN_2N(a, b)    (((a) + (b) - 1) & ~((b) - 1))
	inbuf.pitch[0] = ALIGN_2N(width, 256);
	inbuf.pitch[1] = ALIGN_2N(width, 256);
	inbuf.pitch[2] = ALIGN_2N(width, 256);
	cudaMallocHost((void **)&inbuf.channel[0], inbuf.pitch[0] * height);
	cudaMallocHost((void **)&inbuf.channel[1], inbuf.pitch[1] * height);
	cudaMallocHost((void **)&inbuf.channel[2], inbuf.pitch[2] * height);
	bufsize = width * height * 3 / 2;
	jpegbuf = (uint8_t *)malloc(bufsize);
	// YUVデータをinbufにロードする
	// 詳細はソースコードを参照
	// Encoding
	nvjpegChromaSubsampling_t jpegsamp = NVJPEG_CSS_420;
	size_t jpegsize = bufsize;
	nvjpegEncodeYUV(nvj_handle, nvj_state, nvj_param, &inbuf, jpegsamp, width, height, stream);
	nvjpegEncodeRetrieveBitstream(nvj_handle, nvj_state, jpegbuf, &jpegsize, stream);
	cudaStreamSynchronize(stream);
	// Destroy
	free(jpegbuf);
	cudaFree(inbuf.channel[0]);
	cudaFree(inbuf.channel[1]);
	cudaFree(inbuf.channel[2]);
	nvjpegEncoderParamsDestroy(nvj_param);
	nvjpegEncoderStateDestroy(nvj_state);
	nvjpegDestroy(nvj_handle);
	cudaStreamDestroy(stream);
YUV420Pのロード部分は本質と関係ないことと、若干長いので省略しました。nvJPEG APIの数は少なくてシンプルです。nvJPEGやNVJPGは機械学習用データ(JPEGファイルのことが多いらしい)を高速に入力するため?らしく、デコード命なのでしょう。エンコードもできるけど主眼ではないから、APIもシンプルなものしかないのかな?
前回同様にソースコードを置いておきます。
使い方はコードの先頭にコメントで書いている通りですが、ここでも説明しておきます。引数はありません。ファイル名test_420.yuvのRaw YUV420ファイルを読み込んで、ファイル名simple_420.jpgのJPEGファイルを書き出します。
$ g++ -g -O2 -Wall 20241120_nvjpeg_simple_enc.cpp -lnvjpeg -lcudart $ ./a.out $ ffplay -i simple_420.jpg
エンコード結果はJPEGです。ffplayでも普段お使いの画像ビューアでも、何を使って確認しても構いません。
 この記事にコメントする
 この記事にコメントする
目次: Linux
半年経ったら完全に忘れるのでメモします。最近JPEGのデコードエンコードが必要になって色々調べていました。NVIDIA GPUとCUDAを使ってJPEGが扱えるそうで、API名はnvJPEGだそうです(nvJPEGのAPIドキュメント)。
前回ご紹介したdecoupled decodingは呼び出すべきAPI数が多くて、ウワァ……と引いてしまう見た目でした。今回のsimple decodingはその名の通りシンプルです。ちなみにエンコード側もあります。なぜかsimpleに該当するAPIしかなく、decoupled相当のエンコード用APIは存在しないようです。変なの。
Simple decodingはこんな感じでした。Decoupledと比べるとかなりAPIが少なく済みます。
	cudaStream_t stream = nullptr;
	nvjpegHandle_t nvj_handle = nullptr;
	nvjpegJpegState_t nvj_state = nullptr;
	nvjpegImage_t outbuf = {0};
	uint8_t *img_buf[4] = {nullptr};
	int img_stride[4] = {0};
	int img_sz[4] = {0};
	int r;
	// Create
	cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
	nvjpegCreateEx(NVJPEG_BACKEND_DEFAULT, nullptr, nullptr, NVJPEG_FLAGS_DEFAULT, &nvj_handle);
	nvjpegJpegStateCreate(nvj_handle, &nvj_state);
	//2のべき乗境界に切り上げる
#define ALIGN_2N(a, b)    (((a) + (b) - 1) & ~((b) - 1))
	outbuf.pitch[0] = ALIGN_2N(width, 256);
	outbuf.pitch[1] = ALIGN_2N(width, 256);
	outbuf.pitch[2] = ALIGN_2N(width, 256);
	cudaMalloc(&outbuf.channel[0], outbuf.pitch[0] * height);
	cudaMalloc(&outbuf.channel[1], outbuf.pitch[1] * height);
	cudaMalloc(&outbuf.channel[2], outbuf.pitch[2] * height);
	img_stride[0] = ALIGN_2N(width, 256);
	img_stride[1] = ALIGN_2N(width, 256);
	img_stride[2] = ALIGN_2N(width, 256);
	img_buf[0] = (uint8_t *)malloc(img_stride[0] * height);
	img_buf[1] = (uint8_t *)malloc(img_stride[1] * height);
	img_buf[2] = (uint8_t *)malloc(img_stride[2] * height);
	//Decoupled phase decoding
	nvjpegGetImageInfo(nvj_handle, jpegbuf, jpegsize, &jpegcomps, &jpegsamp, jpegwidths, jpegheights);
	nvjpegDecode(nvj_handle, nvj_state, jpegbuf, jpegsize, NVJPEG_OUTPUT_YUV, &outbuf, stream);
	cudaStreamSynchronize(stream);
	for (int i = 0; i < 3; i++) {
		cudaMemcpy2D(img_buf[i], img_stride[i], outbuf.channel[i], outbuf.pitch[i],
			width, height, cudaMemcpyDeviceToHost);
	}
	// Destroy
	free(img_buf[0]);
	free(img_buf[1]);
	free(img_buf[2]);
	cudaFree(outbuf.channel[0]);
	cudaFree(outbuf.channel[1]);
	cudaFree(outbuf.channel[2]);
	nvjpegJpegStateDestroy(nvj_state);
	nvjpegDestroy(nvj_handle);
	cudaStreamDestroy(stream);
1枚だけJPEGをデコードするならこちらの方が断然楽ですね。
前回同様にソースコードを置いておきます。
使い方はコードの先頭にコメントで書いている通りですが、ここでも説明しておきます。引数はありません。ファイル名test_420.jpgのJPEGファイルを読み込んで、ファイル名simple_420.yuvのRawvideoファイルを書き出します。
$ g++ -g -O2 -Wall 20241120_nvjpeg_simple_dec.cpp -lnvjpeg -lcudart $ ./a.out $ ffplay -f rawvideo -video_size 1920x1440 -pixel_format yuv420p -i simple_420.yuv
デコード結果のRawvideoを確認するときはffplayを使うと便利です。
 この記事にコメントする
 この記事にコメントする
| < | 2024 | > | ||||
| << | < | 12 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 | 
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
| 8 | 9 | 10 | 11 | 12 | 13 | 14 | 
| 15 | 16 | 17 | 18 | 19 | 20 | 21 | 
| 22 | 23 | 24 | 25 | 26 | 27 | 28 | 
| 29 | 30 | 31 | - | - | - | - | 
 25年10月6日
 25年10月6日
 25年10月6日
 25年10月6日
 25年9月29日
 25年9月29日
 25年9月29日
 25年9月29日
 20年8月24日
 20年8月24日
 20年8月24日
 20年8月24日
 16年2月14日
 16年2月14日
 16年2月14日
 16年2月14日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 25年7月20日
 20年8月16日
 20年8月16日
 20年8月16日
 20年8月16日
 20年8月16日
 20年8月16日
 20年8月16日
 20年8月16日
 24年6月17日
 24年6月17日
 24年6月17日
 24年6月17日
 wiki
 wiki Linux JM
 Linux JM Java API
 Java API 2002年
 2002年 2003年
 2003年 2004年
 2004年 2005年
 2005年 2006年
 2006年 2007年
 2007年 2008年
 2008年 2009年
 2009年 2010年
 2010年 2011年
 2011年 2012年
 2012年 2013年
 2013年 2014年
 2014年 2015年
 2015年 2016年
 2016年 2017年
 2017年 2018年
 2018年 2019年
 2019年 2020年
 2020年 2021年
 2021年 2022年
 2022年 2023年
 2023年 2024年
 2024年 2025年
 2025年 過去日記について
 過去日記について アクセス統計
 アクセス統計 サーバ一覧
 サーバ一覧 サイトの情報
 サイトの情報合計: 
本日: