Index
2026-09-03 — Analysis

FurnitureSim(Isaac Gym Preview 4) B200 구동 가능성 점검 및 bring-up

FurnitureBench | 로그인 노드 GPU 1 스모크, worker 검증은 다음 단계

TL;DR

16.1
scripted step/s (1 env)
8/8
B200 Vulkan devices
16줄
FurnitureSim 패치
0
sm_100 torch 커널 (py3.8)

1 배경 / 목적

FurnitureBench(RSS 2023)의 시뮬레이터 FurnitureSim을 클러스터에서 돌리기 위한 사전 점검. FurnitureSim은 NVIDIA가 deprecated한 Isaac Gym Preview 4(2022) 기반으로 공식 요구사항이 Ubuntu 20.04 / Python 3.8 / RTX GPU / torch 1.12+cu113이다.

의심 지점 3가지: (1) PhysX GPU 커널에 Blackwell sm_100 코드가 있는가 — NVIDIA 포럼에 RTX 5080(sm_120) 실패 보고. (2) Isaac Gym은 py≤3.8, B200용 torch(cu128)는 py≥3.9 → 정면 충돌. (3) 헤드리스 K8s pod + datacenter GPU에서 Vulkan 카메라 렌더링이 되는가.

2 작업 내용

2.1 자료 확보

clvrai/furniture-bench 클론(main a87960a, 2024-11-17) + gh-pages 문서 + isaacsim-raytrace 브랜치 확인(오프라인 ray-trace 렌더 스크립트 1개, 시뮬 포트 아님). Isaac Gym Preview 4는 NVIDIA 공식 직링크에서 로그인 없이 다운로드(201 MB).

2.2 커널 아키텍처 분석

cuobjdump --list-elf/--list-ptx libPhysXGpu_64.so ELF: 63×sm_50 63×sm_60 63×sm_70 63×sm_75 63×sm_80 PTX: 63×compute_86 ← 전 모듈 PTX 보유 → sm_100 JIT 가능 libcarb.gym.plugin.so: 3×sm_60 + 3×compute_60 / librlgpu.so: 7×sm_60 + 7×compute_60

2.3 환경 구성

conda create -n furniture-bench python=3.8 pip install torch==2.4.1 --index-url https://download.pytorch.org/whl/cu124 # py3.8 최신 pip install -e isaacgym/python conda install -c conda-forge libegl libgl libglvnd vulkan-tools libusb # Vulkan ICD / pyrealsense2 의존성 pip install pip==22.2.2 setuptools==65.5.0 && pip install -e furniture-bench # gym==0.21.0 핀 export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH; export FURNITURE_SIM_CPU_TENSORS=1

2.4 Vulkan 원인 추적

카메라를 켜면 create_sim에서 segfault(exit 139). vulkaninfo: "Could not get 'vkCreateInstance' via 'vk_icdGetInstanceProcAddr' for ICD libGLX_nvidia.so.0". 시스템 python(RPATH 없음)으로 ICD를 직접 호출하면 negotiate가 -3을 반환하고, LD_DEBUG=libs에서 ICD가 libEGL.so.1을 찾는 것이 보임. pod에는 NVIDIA 벤더 lib만 주입되고 glvnd(libglvnd0)가 없음 → conda glvnd를 LD_LIBRARY_PATH에 올리면 negotiate 0, vkCreateInstance 반환.

2.5 FurnitureSim opt-in 패치 (16줄)

furniture_bench/sim_config.py if os.environ.get("FURNITURE_SIM_CPU_TENSORS") == "1": sim_params.use_gpu_pipeline = False # PhysX는 GPU 유지 furniture_bench/envs/furniture_sim_env.py self.device = cpu if cpu_tensors else cuda:compute_device_id _get_color_obs / depth: [c.cpu() for c in tensors] 후 torch.stack # D2H memcpy만, CUDA 커널 없음 대안: py3.8용 torch를 sm_100 포함 소스 빌드(수 시간, 불확실) / 비-Blackwell GPU 사용 — 패치가 가장 싸고 기본 동작을 바꾸지 않음

3 결과

테스트 (로그인 노드 GPU 1)결과수치
torch 2.4.1+cu124 matmul on B200실패arch list sm_50–sm_90, "no kernel image is available"
Isaac Gym GPU PhysX, 카메라 off (CPU/GPU 파이프라인)OK40 frame 0.11 s
Isaac Gym + 카메라, glvnd 없음segfaultexit 139 at create_sim
Isaac Gym + 카메라, conda glvndOKGPU pipeline 60 frame 1.65 s, 카메라 텐서 cuda:1 → .cpu() 정상
vulkaninfo / EGLOKB200 ×8 Vulkan 1.4.312; OpenGL 4.6.0 컨텍스트
FurnitureSim 원본 (GPU 텐서)실패create_envs의 첫 torch.zeros(cuda)에서 no kernel image (Isaac Gym init·SDF cooking은 통과)
FurnitureSim + CPU_TENSORS, zero-actionOKenv 생성 14.5 s, 30 step 4.4 s (6.8 step/s), obs (1,224,224,3) uint8 cpu
FurnitureSim + CPU_TENSORS, scripted one_legOK100 step 6.2 s (16.1 step/s), reach→pick→push→release→go_up, skills_done=2
step 0
Figure 1: one_leg step 0 — 손목 카메라(좌) / 전면 카메라(우), 224×224
step 99
Figure 2: step 99 — scripted agent가 테이블탑을 잡고 이동, AprilTag 렌더링 확인
핵심 발견: B200에서 Isaac Gym 물리(PTX JIT)와 Vulkan 렌더링 모두 동작한다. 실패 원인은 GPU가 아니라 (a) pod의 glvnd 부재, (b) py3.8 torch의 sm_100 미지원 두 가지였다.
제약: py3.8 torch로는 같은 프로세스에서 GPU 정책 추론 불가(R3M/VIP env 포함). worker pod 검증은 클러스터 만석(120/120)으로 미실시.

4 Takeaway

의미

FurnitureSim을 이 클러스터에서 쓸 수 있는 경로가 확보됐다. CPU 텐서 파이프라인이지만 1 env 기준 6.8–16 step/s로 데모 replay·scripted 데이터 수집·정책 평가에는 충분하다. 정책 네트워크는 py3.10+ 별도 프로세스(또는 CPU)로 분리하는 구조가 필요하다.

5 Next Steps

worker pod 검증

conda activate furniture-bench && sbm "bash scripts/run_scripted_one_leg.sh" --gres=gpu:1 -c 8 --mem 200GB --qos=extra --time 1:00:00 — 로그의 [env] vulkan ICD / dri 줄로 worker 이미지의 /etc/vulkan/icd.d, /dev/dri 주입 여부 확인. 없으면 admin에게 graphics capability 요청.

처리량 / 데이터

num_envs별 step/s 측정(문서상 multi-env 미최적화). 공식 sim 데모 다운로드 후 run_sim_env --file-path replay 검증.

대안 검토

py3.8 torch를 sm_100 포함 소스 빌드하면 GPU 파이프라인 복원 가능하나 비용이 큼. 비-Blackwell GPU 머신이 있으면 원본 그대로 실행 가능.

6 업데이트 — scripted 데모 수집 디버깅 (low vs med)

pi0.5용 sim 데모를 공식 scripted agent로 만들기 전에, 로그인 노드 디버깅 범위(≤5분, GPU 1장)에서 med 동작 여부·에피소드 비용·성공률 대략치를 확인했다. collect_data.py --scripted --is-sim --headless --pkl-only --resize-sim-img --save-failure --num-demos 1, timeout 300 s.

레벨에피소드성공길이skill 완료 step (4개)비고
low3 (2 min)1 (515 step)실패 2건 601 = timeout~35 / ~70 / 140~160 / 226~2895번째 phase(insert+screw)에서 timeout
med7 (5 min)0전부 601 = timeout~35 / ~70 / 114~173 / 201~291앞 4 skill은 low와 동일, insert/screw 전부 timeout
병목은 insert+screw: med에서도 앞 4 skill(테이블탑 잡기/밀기, 다리 잡기/이동)은 안정적. 성공 케이스도 screw에 ~290 step을 쓰므로 공식 timeout 600이 빡빡하다. 표본이 작아(low 3, med 7) 성공률은 sbatch 결과로 대체해야 한다.
에피소드당 ~40 s (≈15 step/s), pkl 156 MB(성공) / 182 MB(timeout) 비압축 → 1000 성공 데모 ≈ 150~180 GB low 33% 가정: 성공 1개당 ~2 min → 300개 ≈ 10 GPU·h, 1000개 ≈ 33 GPU·h (job 분할 필수) 추가: scripts/collect_scripted.sh <low|med|high> <N> [out_root] [timeout] (sbm용, 성공률 요약 출력) sim_config.py에 FURNITURE_SCRIPTED_TIMEOUT env 오버라이드 (기본 600 유지)

수집 에피소드 영상 (손목 | 전면, 20 fps = 2배속)

low 성공 (515 step): insert 후 screw 반복으로 조립 완료
low 실패 (600 step timeout): 앞 4 skill 완료 후 insert/screw에서 timeout
med 실패 (600 step timeout): 초기 배치 ±5 cm/±45° 섭동, 앞 4 skill은 동일하게 성공

다음

sbatch로 low/med 각 20~30 에피소드를 timeout 600 vs 1000으로 비교해 성공률 확정. med가 timeout을 늘려도 0%에 가까우면 insert/screw 스크립트의 med 대응 수정 필요.

7 업데이트 — worker pod 수집 calibration (성공 20개씩 × 4 설정)

sbmr(extra, 1 GPU)로 제출. 1차는 worker 이미지에 libgomp/glib가 없어, 2차는 C++ 컴파일러가 없어(gymtorch JIT 빌드) 즉시 실패 → conda-forge libgomp glib xorg-libx11 libxcb gxx_linux-64 libxcrypt + opencv-python-headless + CPATH로 해결(venv-only 정책 유지). 3차(107994~107997)가 정상 완료.

설정에피소드성공률성공 길이 mean(max)실패소요성공 1개당
low, t600440.45482 (542)24 (전부 timeout)23:4471 s
low, t1000380.53511 (662)18 (전부 timeout)27:2082 s
med, t600540.37483 (567)34 (전부 timeout)33:23100 s
med, t1000390.51536 (735)19 (전부 timeout)31:5696 s
worker 렌더링 OK: GPU util ~60%, VRAM 2.4 GB, CPU 4%/8코어. GPU 1장에 프로세스 4개 + OMP_NUM_THREADS=2가 본 수집의 기본 구성.
timeout: 1000은 600~750 step 성공을 더 건지지만 실패가 1001 step까지 늘어 성공 1개당 비용은 동률(low +15%, med −4%). 성공 최대 735 step → 800이 절충안(미검증). 실패는 전부 insert+screw 단계 timeout이라 근본 개선은 스크립트 쪽.
본 수집 비용(성공 1개당 ~85 s): 300개 ≈ 7 GPU·h ≈ 1 GPU×4proc 1.8 h / 1000개 ≈ 24 GPU·h ≈ 2 GPU×4proc 3 h 용량 ~170 MB/에피소드 (실패 포함 저장 시 성공 1개당 ~350 MB) sbmr 20 "bash scripts/collect_scripted.sh low 300 data/scripted_sim 800" --gres=gpu:1 --ntasks=4 --cpus-per-task=2 --mem 200GB --qos=extra --time 6:00:00

8 업데이트 — 가구 4종 300개 수집, pkl→LeRobot 변환기, pi0.5 학습/평가 파이프라인

8.1 가구별 scripted calibration (low, 성공 20개, 공식 timeout)

가구에피소드성공률평균 길이성공 1개당 (GPU당)300개 GPU·h본 수집 분할
one_leg440.4554770 s62 × 150 (4proc)
lamp290.6975589 s7.42 × 150
round_table410.491199159 s133 × 100
cabinet790.251356306 s285 × 60
GPU당 처리량은 프로세스 수와 무관: one_leg 4proc job이 62~74 s/성공으로 1proc(71 s)과 같음(GPU util 80%, GPU-bound). 병렬화는 job 수로. round_table/lamp FSM의 acos 입력이 float32 오차로 1을 넘어 NaN → CPU eigh 크래시 → clamp 패치.

8.2 파이프라인 (수집 완료 후 실행)

1) 변환 (openpi env = lerobot 0.3.3 → v2.1 포맷; pi05 env의 0.4.3/v3.0과 섞으면 안 됨) sbm "bash scripts/convert_all_lerobot.sh" --gres=gpu:0 -c 16 --mem 64G --qos=extra --time 4:00:00 → data/lerobot/furniture_sim/{one_leg,lamp,round_table,cabinet}_low, all_low keys: image(front) / wrist_image / state 15 / actions 7 (dpos3 + axis-angle3, w≥0 정규화 + gripper) / task 프롬프트 2) 학습 (scenemem/openpi config pi05_furniture_one_leg_low: pi05_libero 기반 2뷰, horizon 10, batch 32, 30k step) sbm "bash scripts/train_pi05.sh pi05_furniture_one_leg_low one_leg_low_v1" --gres=gpu:1 -c 8 --mem 200GB --qos=extra --time 24:00:00 3) 평가 (1 GPU 안에서 policy server(openpi env) + FurnitureSimFull-v0 클라이언트(furniture-bench env, openpi_client)) sbm "bash scripts/eval_pi05_furniture.sh pi05_furniture_one_leg_low <ckpt> one_leg 20" --gres=gpu:1 -c 8 --mem 200GB --qos=extra --time 4:00:00
검증 완료: 5ep 변환 → norm stats → 학습 스모크 50 step(loss 0.147→0.060, 체크포인트 저장) → 그 체크포인트로 policy server ↔ FurnitureSim 클라이언트 e2e(30 step, 6 call) 통과.
로그인/환경 함정: ~/.local/bin/gsutil이 깨진 shim이라 PATH에서 제거(익명 gcsfs 폴백); Isaac Gym graphics_device_id는 Vulkan 인덱스라 클라이언트는 CUDA_VISIBLE_DEVICES 없이 물리 GPU 지정; 로그인 포트 8000 점유 → free port.

8.3 one_leg 학습 제출

데이터셋 furniture_sim/one_leg_low: 344 ep / 175,145 frames (A 304 + B 316 성공 중 300 + calib 40; 성공률 0.57~0.58 @ timeout 800) job 108379 fb_train_one_leg_v1: pi05_furniture_one_leg_low, 30k step, batch 32, 1 GPU, sbmr 10 (requeue 시 --resume) 평가: 5k step 체크포인트마다 scripts/eval_pi05_furniture.sh … one_leg 20 → 성공률 (기준선 IQL-R3M ≈ 0.4~0.5, scripted 0.45~0.58)

9 업데이트 — pi0.5 학습 진행·첫 평가, LingBot-VA 트랙

9.1 pi0.5 one_leg (run yhc0752v)

steplossgrad_norm비고
00.1081.28pi05_base 초기화
20000.0160.101k step ≈ 18 min
50000.013—체크포인트 직후 PREEMPTED → 108562로 재개(--resume)
step 5000 평가 (20 ep): timeout 600·1000 모두 성공 0. phase 히스토그램(1000 step): 1→10, 2→8, 3→2 (평균 1.6/4). 테이블탑 밀기 20/20, 다리 들기 9/20, 8 cm 이내 접근 3/20, 조립 0. 테이블탑을 20 cm 이상 밀어내는 경우 7/20. → "느린 것"이 아니라 insert/screw 미학습. 10k/20k/30k에서 재평가.
worker 함정 3개 (런처에 반영): wandb TLS(x509) → SSL_CERT_FILE=certifi; 체크포인트 경로는 절대경로(서버가 openpi 체크아웃에서 실행); Isaac Gym graphics_device_id는 Vulkan 인덱스 → 클라이언트는 CUDA_VISIBLE_DEVICES 없이 물리 GPU 지정 평가 스크립트에 phase proxy(base_moved / leg_lift / leg_base_dist_min / n_assembled) 추가

9.1b step 5k vs 10k (20 ep, timeout 1000, phase proxy)

지표5k10k
평균 phase (0~4)1.602.45
phase 분포1:10 / 2:8 / 3:21:1 / 2:9 / 3:10
다리 들기 >3 cm9/2019/20
테이블탑 8 cm 이내3/2010/20
3 cm 이내(삽입 직전)1/205/20
테이블탑 20 cm+ 밀어냄7/202/20
성공00
병목 = 삽입 정밀도. 데이터의 57%(평균 304/536 step)가 insert+screw 구간이라 커버리지 부족은 아님. 학습 초반(10k/30k) 또는 5-step 재계획이 미세 조작에 불리한지 확인 중(replan 10 평가 108748). 20k/30k 재평가 예정.
체크포인트 (replan 10, 20 ep)성공다리 들기접근 <12 cm<3 cm
10k2/2013142
20k1/20 (518 step)17156
첫 성공 (10k, replan 10): 같은 체크포인트에서 재계획 주기 5→10(청크 전체 실행)으로 바꾸자 2/20 성공(771, 677 step). 이후 평가는 replan 10 기본.
pi0.5 10k, replan 10 — one_leg 조립 성공 에피소드 (손목 | 전면)

9.2 LingBot-VA (video-action world model) 트랙

단일팔 지원 확인(30-D canonical action의 왼팔 슬롯; LIBERO config = Franka 단일팔·2뷰·10 Hz·7-D → FurnitureSim과 동일). 학습은 FlexAttention이라 flash-attn 불필요. lingbot-va-base 24.4 GB 캐시, env lingbot-b200(torch 2.9.0+cu128 sm_100, lerobot 0.3.3).

데이터: prepare_lingbot_dataset.py (action_config, action 컬럼, norm_stat) → extract_latents.py (Wan2.2 VAE mu 정규화 (f h w) c bf16 CPU, UMT5 512 토큰, empty_emb.pt; 128², 4k+1 프레임) 잡은 문제: .pth에 CUDA 텐서 저장 → fork 워커 CUDA 재초기화 에러 / 텍스트 226 토큰 → block_mask(…,512) 불일치 / LeRobot이 mp4가 아닌 PNG 저장 스모크(1 GPU, 6 step): action_loss 0.53→0.39, ~2.5 s/step → 본 학습 108687 (2 GPU, 5000 step, latent 추출 108681 완료 후 시작)