반응형

Intro

안녕하세요. 오늘은 오랜만에 대학 동기들과 모임회비로 바이킹스워프 광교점에 다녀왔습니다. 바이킹스워프는 처음 가봤는데 너무 맛있었고 좋았던 기억이라 같이 공유드립니다 ㅎㅎ

 

위치 및 장소

 

바이킹스워프 광교점은 아비뉴프랑 광교점 1층에 있습니다. 지하 주차장에 주차 하시면 편하게 이용이 가능합니다! 

이용시간

[수~금] 런치: 12:00 ~ 15:00 / 디너: 18:00 ~ 21:00 (*월,화 휴점)[주말 및 공휴일]
런치 1부: 11:30~13:20 / 런치 2부: 13:40~15:30
디너 1부: 17:00~18:50 / 디너 2부: 19:10~21:00

가격 정보

110 달러 (3인 기준 446,160원, 1인당 148,720원 )

매장 이용

손씻는 장소

처음 매장을 방문하면 손을 씻도록 안내 해줍니다 ㅎㅎ. 청결 중요!

랍스타 찜

랍스터 찜 살이 야들야들하고 엄청 맛있습니다.

육회

육회는 정말 별미 입니다 ㅎㅎ. 하지만 양이 작아서 자주 가져와야 됩니다. 양이 많으면 좋을 것 같습니다. 맛은 정말 맛있습니다.

초밥 사시미

초밥과 사시미는 직원한테 가서 먹고 싶은 초밥을 주문하는 시스템입니다. 초밥 정말 맛있습니다.

랍스타 스프

랍스터 수프도 정말 맛있습니다.

만찬

소갈비도 꼭 먹어 보세요!! 

마무리

이번 포스팅은.. 원래 포스팅할 생각이 없었고, 여자친구한테 보내줄 사진으로 몇 장 찍어봤는데.. 생각해 보니 가격은 비쌌지만 너무 맛있었고 즐거운 시간이라서 포스팅하게 되었습니다. 가격은 정말 후들후들 하지만 모든 메뉴가 맛있었습니다. 그리고 뷔페이지만 매장이 생각보다 작았습니다. 작아서 그런지 모든 메뉴가 뷔페처럼 만들어 놓은 게 아닌 손님이 직원에게 요청하면 그때 바로 만들어 주는 시스템이었습니다. 그리고 디저트 사진을 찍지 못했지만 아이스크림과 케이크도 너무 맛있었습니다.  그래도.. 가격은 너무 비싸서 자주 못 오고 특별한 날에는 꼭 한번 더 방문 할 것 같습니다 ㅎㅎ

 

반응형
반응형

Intro

안녕하세요. 이번 포스팅은 여주 프리미엄 아울렛을 갈 때 필수로 들리는 코스와 맛집을 추천하려고 합니다!  저는 여주 프리미엄 아울렛을 갈 때 근처에 있는 K2 팩토리와 응암본가라는 맛집을 항상 가는데요. K2는 정말 저렴한 최저가로 등산 용품을 구매할 수 있고, 응암본가는 아울렛에서 거리가 아주 가깝지 않지만, 모든 반찬이 정말 맛있고, 만족스러웠습니다.

 

위치 및 장소

K2 팩토리

K2 팩토리는 여주 프리미엄 아울렛에서 차로 10분 거리에 있습니다. 

K2팩토리 장소

매장

K2팩토리 매장

K2팩토리의 매장 안에는 K2뿐만 아니라 아이다 W.ANGLE, DYNAFIT의 브랜드의 물품이 있었고, 진짜 정말 정말 아주 쌉니다. 인터넷 최저가보다 싼 경우도 많이 봤습니다. 제가 방문한 날은 마음에 드는 물품이 없어서 구매하지 못했지만, 운이 좋으면 정말 싸게 많이 구매할 수 있습니다. 다음은 제 인생 맛집 응암본가입니다.

위치 및 장소

응암본가 위치
응암본가

응암본가는 아울렛에서 20분 정도 떨어진 위치에 있습니다. 주차장이 넓어 편하게 주차하실 수 있습니다.

음식

메뉴판

메뉴는 본가정식, 간장게장 정식, 장어 정식으로 구성되어 있습니다. 예전에는 본가번식보다 저렴한 정식이 있었는데, 없어졌네요 ㅎㅎ  저는 본가정식으로 2인분 주문했습니다. 다른 정식도 전부 먹어봤지만, 본가정식이 가격대비 괜찮더라고요 ㅎㅎ

본가 정식

음식은 사진과 같이 다양하게 나옵니다. 그런데.. 여기는 맛이 없는 반찬이 하나도 없습니다. 진짜 모든 반찬이 맛있습니다 ㅎㅎ 된장찌개도 옛날 된장 찌개 맛이라 정말 맛있습니다. 

음식 다 먹은 사진

진짜 배부르게 다 먹었습니다. 여기는 모든 반찬을 다 드셔보시길 추천드립니다. 특히 열무김치 진짜 맛있습니다!!

 

응암본가 채소 밭

나갈 때 보니 손님이 드시는 채소를 직접 재배를 하는 것 같더라고요. 저걸 보니 더욱 믿음이 갔습니다.

 

마무리

이번 포스팅은 제가 여주 프리미엄 아울렛을 갈 때 꼭 들리는 K2  팩토리와 응암본가라는 맛집을 소개 했습니다. 여주 아울렛을 방문하실 때 참고 하시면 될 것 같아요 ㅎㅎ. 그러면 즐거운 쇼핑되시길 바랍니다~ 감사합니다.

반응형
반응형

Intro

안녕하세요. 오늘은 여주 프리미엄 아울렛을 방문한 즐거운 경험을 공유하려 합니다. 저는 아울렛을 엄청 자주 가는 편인데, 신세계 여주 아울렛이 명품이 가장 많고 크기 때문에 자주 방문하고 있습니다.

위치 및 장소

여주 프리미엄 아울렛은 서울에서 차로 약 1시간 정도 거리에 있어서, 접근성이 좋다는 장점이 있습니다. 차로 오기 편리하며, 최근에는 강남에서 갈 수 있는 버스가 생겨서 대중교통을 이용해도 도착할 수 있습니다. 

만약, 여주 프리미엄 아울렛을 자차로 방문하게 된다면 꿀팁이 하나 있습니다. 바로 여주 아울렛에는 실내 주차장이 있습니다!! 실내 주차장이 있는지 모르고 지상에다 주차하시는 분이 많은 걸로 알고 있습니다. 여름에 비가 오거나 눈이 올 때는 실내 주차장에 주차를 하면 편하게 쇼핑할 수 있습니다!! 

여주 프리미엄 아울렛 실내 주차장 위치
여주 프리미엄 아울렛 실내 주차장
매장 입구

다양한 브랜드와 상품

여주 프리미엄 아울렛은 명품을 포함한 스포츠 의류, 신발, 가방, 액세서리 등 다양한 상품을 만날 수 있어요. 나만의 스타일을 찾을 수 있는 최적의 장소입니다.

여주 프리미엄 아울렛 지도

여주 프리미엄 아울렛은 WEST와 EAST로 구분이 되어 있습니다! 정말 넓고 쾌적하게 쇼핑을 즐길 수 있습니다. 하지만 전부 돌아보기에는 강인한 체력과 힘이 있어야 합니다!  아 참고로 실내 주차장에 주차를 하게 되면 WEST와 붙어 있기 때문에 참조하시면 됩니다!!

아디다스

실내 주차장에서 주차를 하고 나오면 제일 먼저 아디다스를 볼 수 있습니다. 

아디다스 세일 정보

지금 아디다스는 2PCS 구매 시 추가 20% 할인 행사를 하고 있네요 ㅎㅎ

다음은 WEST에 있는 명품 라인입니다~ 

지방시
생로랑, 발렌시아가
보테가베네타
코치
나이키

EAST로 넘어가면 가장 먼저 만날 수 있는 나이키입니다!

나이키 실내
나이키 실내
나이키 할인정보

다음은 EAST의 명품 라인입니다. EAST의 중앙의 분수대를 기준으로 주변에 다양한 명품이 많습니다!

EAST 분수대

 

버버리

버버리는 매장이 1층은 여성용품, 2층은 남성 용품으로 구성되어 있습니다.

버버리 1층 여성용품
버버리 2층 남성용품

 

버버리 할인정보
프라다

주말에는  기본 1시간 이상 줄 서야 하는 프라다입니다!! 제 생각에는 여주 프리미엄 아울렛에서 가장 인기가 많은 매장인 거 같아요. 저도 가방 몇 번 산적이 있지만.. 항상 기다렸습니다 ㅎㅎ

구찌

다음은 프라다 다음으로 인기가 많은 구찌입니다. 

몽클레어
음식점

프라다 옆 음식점입니다~

마무리

여주 프리미엄 아울렛은 다양한 쇼핑 명소 중에서도 특별한 곳 중 하나입니다. 할인 가격, 다양한 브랜드, 편안한 환경, 맛있는 음식 등 모든 조건을 갖춘 곳으로, 패션과 쇼핑을 즐기는 분들에게 강력히 추천합니다. 다음 번 방문 때는 더 많은 발견을 기대하며, 여주 프리미엄 아울렛의 아름다운 경험을 함께 나눠보세요!

여주 프리미엄 아울렛 방문 후의 쇼핑 힐링은 정말로 최고입니다. 여러분도 이곳을 방문하여 스타일을 업그레이드하고 특별한 아이템을 발견하는 재미를 느껴보세요. 즐거운 여행과 쇼핑되세요! 

다음 포스팅은 여주 프리미엄 아울렛을 갈 때 꼭 들리는 K2 팩토리 매장과 여주 갈 때마다 찾는 로컬 맛집을 추천 드리겠습니다! 감사합니다!

 

참고. 할인 정보는 여주 프리미엄 아울렛 공식 사이트에서 찾아보실 수 있습니다!!

https://m.premiumoutlets.co.kr/yeoju/sales_events/in_store_promotions

반응형
반응형

 

Intro

안녕하세요. 오늘은 저희 가족이 정말 좋아하는 수원 광교의 돼지갈비 무한리필인 명륜 진사갈비를 소개해볼까 합니다. 최근에 명륜 진사갈비가 리뉴얼되고 평가가 좋아져서 짝꿍과 같이 가게 되었습니다 ㅎㅎ

위치 및 장소

명륜 진사갈비 광교점 위치

위치는 광교 푸르지오 월드마크 아파트 옆인 광교 스타힐스 주차장으로 들어 가시면 됩니다. 주차장은 넓고 쾌적하며, 다른 명륜진사갈비 지점과 비교했을 때 편하게 주차할 수 있었습니다. 명륜 진사 갈비는 2층에 위치하고 있습니다. 지하주차장에서 엘리베이터를 타고 올라가면 편하게 도착할 수 있습니다.

입구 사진

가격 정보

명륜진사갈비 광교점 가격 정보

가격은 1인당 18,900원 입니다. 요즘 같은 고물가 시대에 이 정도 가격에 돼지갈비와 삼겹살 등을 무한으로 먹을 수 있다니 너무 가성비 최고입니다 ㅎ.

매장 사진

매장 사진

 

고기 사진

저희가 5시에 바로 와서 아직 고기가 체워지지 않았어요 ㅎㅎ 하지만 1분 이내에 바로 고기를 채워 주셨어요~

샐러드바

매장에서는 다양한 고기를 제공하며 샐러드바에서 마음대로 고기에 곁들일 음식을 가져 올 수 있습니다. 특히 떡을 구워 먹으면 정말 맛있어요 ㅎㅎ.  건너편에 추가로 떡볶이, 잡채 등이 있었지만 고기에 집중하기 위해 패스했습니다~!

 

음식 사진

돼지갈비와 떡

처음에 오시면 뼈에 붙은 돼지갈비 한판을 먼저 주십니다. 셀프바에는 보통 목전지가 많고 갈비가 붙은 게 적은데, 뼈에 붙은 갈비를 드시고 싶으면 호출해서 말씀하시면 됩니다ㅎㅎ. 눈치 보지 마세요 ㅋㅋ 사장님이랑 알바 굉장히 친절해요.

목살과 삼겹살
뼈등심
맛보기 비빔냉면
갈비 햄버거

갈비 햄버거는 정말 맛있습니다!! 꼭 먹어보시길 강추드려요 ㅎㅎ

셀프 불판

불판을 셀프로 교체할 수 있어서 너무 좋았습니다. 

 

마무리

수원 광교지역에서 점심이나 저녁 식사 장소를 찾고 있다면, 명륜진사갈비 수원 광교점을 강력히 추천합니다. 이곳을 방문해서 먹은 갈비, 삼겹살, 목살, 뼈삼겹 등의 고기는 정말로 맛있었습니다.

특히 돼지갈비는 그 맛을 잊을 수 없을 정도로 훌륭했습니다. 다른 데는 보통 1인분에 2만 원 정도 해서 돼지갈비 먹다가 모자라면 추가로 시키기 눈치 보였는데 요즘 같은 고물가 시대에 이 정도 가격에 돼지갈비를 무한으로 먹을 수 있다니 너무 좋았습니다!!  거기에 맛도 생각보다 너무 괜찮았습니다.

또한 주차도 편리했습니다. 주차는 2시간 무료로 제공해 줘요.

불판의 불도 적절하게 조절되어 있어 고기를 구울 때 불을 조절할 필요가 없어 좋았습니다. 특히 불판을 셀프로 교체할 수 있어서 너무 편했습니다. 다른 지점은 불판에 손잡이가 없어서 집개로 불판을 교체하다 보니 불편했는데 여기는 불판에 손잡이가 있어서 저 같은 초보도 쉽게 불판을 셀프로 교체할 수 있었습니다. 

이런 편의성과 맛있는 고기로 인해 명륜진사갈비 수원 광교점은 저의 식사 경험을 향상해 준 최고의 장소 중 하나였습니다. 다음번 광교에서의 방문을 기대하며, 여러분도 한번 방문해 보시기를 권장합니다.

반응형
반응형

Intro

안녕하세요. 최근 회사에서 대용량 데이터 처리 관련 업무를 하며 GPU에 대한 관심을 갖게 되었습니다. 컴퓨터 성능에 관심이 있다면, CPU와 GPU라는 용어를 들어본 적이 있을 것입니다. 이 두 가지는 현대 컴퓨터 시스템에서 핵심적인 부품으로써 역할을 하며, 각각 고유한 기능과 특징을 갖고 있습니다. 이 글에서는 CPU와 GPU의 기본적인 기능과 차이점에 대해  설명하겠습니다.

 

CPU vs GPU

CPU (Central Processing Unit)란?

  • CPU는 컴퓨터의 두뇌로 불리는 중앙 처리 장치입니다. 주요 기능은 컴퓨터의 모든 연산과 작업을 관리하고 조정하는 것입니다. 컴퓨터의 주요 명령어를 해석하고 실행하는 역할을 수행하여 사용자와 시스템이 원활하게 상호작용할 수 있도록 합니다. 

CPU 특징

  • 제어 유닛(Control Unit): 명령어를 해석하고 실행하는 데 필요한 신호 제어
  • 산술 논리 연산 장치(ALU, Arithmetic Logic Unit): 산술 및 논리 연산 수행
  • 캐시 메모리(Cache Memory): CPU 내부에 위치하여 빠른 데이터 접근 지원
  • 스레드(Thread): 하나의 CPU 코어에서 동시에 여러 작업을 처리할 수 있는 스레드 지원


GPU (Graphics Processing Unit)란?

  • GPU는 그래픽 처리에 특화된 장치로서, 3D 그래픽 및 영상 처리 작업에 사용됩니다. 초기에는 그래픽 작업을 위해 개발되었지만, 현대의 GPU는 고성능 병렬 처리 능력을 갖추고 있어 일반적인 병렬 계산 작업에도 사용됩니다. 고성능 병렬 처리 능력을 갖추고 있기 때문에 비트코인 같은 채굴 연산에 많이 사용됩니다.

GPU 특징

  • 병렬 처리: 많은 코어로 구성되어 동시에 많은 연산을 병렬로 처리
  • 특수 목적: 주로 그래픽 연산을 위해 설계되었지만, GPGPU(General - Purpose computing on Graphics Processing Units) 기술을 통해 일반적인 계산에도 사용
  • 메모리 계층: CPU보다 큰 메모리를 가지며, 각 코어 당 작은 캐시 메모리를 갖고 있어 대규모 데이터 처리에 유리

CPU와 GPU의 차이

기능 및 용도

  • CPU는 일반적인 계산, 시스템 작업, 사용자 인터페이스 등 다양한 작업을 처리하는 데 사용
  • GPU는 그래픽 렌더링, 게임, 영상 편집, 인공지능, 데이터 마이닝 등 병렬 처리가 중요한 작업에 특화

코어의 구조

  • CPU는 몇 개의 코어(주로 2개~16개)를 가짐
  • GPU는 수백 개에서 수천 개의 코어를 가지며, 이는 대량의 데이터를 동시에 처리하는 데 유리

처리 방식

  • CPU는 순차적으로 작업을 처리하며, 각 코어가 하나의 작업을 순서대로 수행
  • GPU는 병렬 처리를 통해 많은 작업을 동시에 처리하며, 단일 작업을 여러 코어가 분담

속도와 성능

  • CPU는 단일 코어 당 높은 성능
  • GPU는 대량의 코어가 병렬 처리를 지원하여 대규모 데이터 처리에 뛰어난 성능을 보임

전력 소비

  • CPU는 전력 소비가 적으며, 에너지 효율적임
  • GPU는 많은 코어로 인해 전력 소비가 높을 수 있음

(※ 그림으로 보면 GPU에 CPU가 여러 개 들어 있는 걸로 보이지만 아니다. CPU의 단순 계산적 기능적인 부분을 GPU가 병렬 처리하는 부분을 쉽게 설명하기 위해 위와 같이 표현하였다.)

    • CPU는 직렬 처리에 최적화된 몇 개의 코어로 구성. 반면, GPU는 병렬 처리용으로 설계되었다. 작고 효율적인 코어로 구성
    • CPU는 순차적인 작업에 강점. GPUCPU보다 많은 코어의 수로 병렬적인 작업에 강점

마무리

최근 대용량 데이터 처리 관련 업무를 하며 GPU를 활용한 병렬 처리를 검토하고 있어서 CPU와 GPU의 간단한 차이에 대해 알아봤습니다. CPU와 GPU는 모두 컴퓨터 시스템에서 중요한 역할을 하며, 각각의 특징과 용도에 따라 다른 작업에 최적화되어 있습니다. CPU는 다양한 일반적인 작업을 처리하는 데 사용되고, GPU는 그래픽 및 대규모 병렬 처리가 필요한 작업에 특화되어 있습니다. 현대 컴퓨팅은 CPU와 GPU를 조합하여 최상의 성능과 효율성을 달성하는 것이 일반적입니다. 이러한 CPU와 GPU의 차이를 알고 소프트웨어를 개발하면 좋을 것 같습니다.

 

반응형
반응형

Intro

안녕하세요. 이번에는 시리얼 통신에 관한 설명과 간단한 샘플 코드 소개 하겠습니다. 시리얼 통신은 컴퓨터나 다른 장치들 사이에서 데이터를 주고받는 데에 사용되는 일련의 통신 방법입니다. 주로 마이크로컨트롤러, 아두이노, 센서, 모터 등과 같은 장치들을 컴퓨터와 연결하여 데이터를 교환하고 제어하는 데에 많이 사용됩니다. 

시리얼 통신 설명

1. 시리얼 통신의 기본 개념

  • 시리얼 통신은 비트들이 연속적으로 전송되는 방식으로, 병렬 통신과는 달리 하나의 비트씩 순차적으로 전송됩니다. 데이터를 주고받을 때는 두 장치 간에 공통된 데이터 송수신 (TX/RX) 핀을 사용하며, 주로 UART(Universal Asynchronous Receiver/Transmitter) 프로토콜을 기반으로 합니다.


2. UART 프로토콜

  • UART는 가장 일반적으로 사용되는 시리얼 통신 프로토콜 중 하나로, 비동기적으로 데이터를 전송합니다. 비동기적이라는 의미는 클록 신호가 없이 데이터 비트를 전송한다는 것을 의미합니다. UART는 데이터 비트, 정지 비트, 패리티 비트로 구성됩니다.



3. 시리얼 통신의 속도

  • 시리얼 통신에서는 속도를 보드레이트(baud rate)라고 부릅니다. 보드레이트는 초당 전송되는 비트의 수를 나타내며, 일반적으로 흔히 사용되는 보드레이트는 9600, 19200, 38400, 115200 등이 있습니다. 속도는 통신하는 장치들 사이에서 동일해야 정상적으로 데이터를 주고받을 수 있습니다.

4. 시리얼 통신의 연결

  • 시리얼 통신을 위해 두 장치를 연결할 때는 보통 UART 케이블이나 USB 시리얼 어댑터를 사용합니다. 컴퓨터의 경우 UART를 지원하는 시리얼 포트나 USB를 통해 시리얼 통신을 할 수 있습니다.


5. 시리얼 통신의 사용 예

  • 시리얼 통신은 다양한 분야에서 사용됩니다. 예를 들어, 아두이노와 컴퓨터를 연결하여 센서 데이터를 읽거나 제어 신호를 보낼 수 있습니다. 또한, 마이크로컨트롤러를 이용한 로봇 제어, 센서 네트워크 구축, 원격 감시 시스템 등에도 적용될 수 있습니다.

소스 코드(C++)

헤더

#define PORT_COMMUNICATIONSIZE 512
#include<string>
class SerialPort
{
private:
	HANDLE				m_hComm;
	DCB					m_dcb;
	COMMTIMEOUTS		m_CommTimeouts;
	bool				m_bPortReady;
	bool				m_bWriteRC;
	bool				m_bReadRC;
	unsigned long		m_iBytesWritten;
	unsigned long		m_iBytesRead;
	unsigned long		m_dwBytesRead;
public:
	SerialPort();
	~SerialPort();
	bool OpenPort(std::string portname);
	bool ClosePort();
	bool PortConfigure(unsigned long BaudRate, unsigned char ByteSize, unsigned long fParity, unsigned char  Parity, unsigned char StopBits);
	bool SetCommunicationTimeouts(unsigned long ReadIntervalTimeout, unsigned long ReadTotalTimeoutMultiplier,
		unsigned long ReadTotalTimeoutConstant, unsigned long WriteTotalTimeoutMultiplier,
		unsigned long WriteTotalTimeoutConstant);
	bool ReadPortRegister(unsigned char* Register);
	bool WritePortRegister(unsigned char* Register, int length);
};

본문

#include "SerialPort.h"
SerialPort::SerialPort()
{
	m_hComm = NULL;
	m_dcb = { 0 };
	m_CommTimeouts.ReadIntervalTimeout = 0;
	m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	m_CommTimeouts.ReadTotalTimeoutConstant = 0;
	m_CommTimeouts.WriteTotalTimeoutConstant = 0;
	m_CommTimeouts.WriteTotalTimeoutConstant = 0;
	m_bPortReady = false;
	m_bWriteRC = false;
	m_bReadRC = false;
	m_iBytesWritten = -1;
	m_iBytesRead = -1;
	m_dwBytesRead = -1;

}
SerialPort::~SerialPort()
{
	CloseHandle(m_hComm);
}
bool SerialPort::OpenPort(std::string portname)
{
	m_hComm = CreateFileA(portname.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL,
		OPEN_EXISTING, 0, NULL);
	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		//OutputLog::LOG("Simulator - Serial Port Open Fail\n", OutputLog::LogLevel::System);
		return false;
	}
	else
	{
		//OutputLog::LOG("Simulator - Serial Port Open Sucess\n", OutputLog::LogLevel::System);
		return true;

	}

}

bool SerialPort::ClosePort()
{
	CloseHandle(m_hComm);
	m_hComm = NULL;
	if (m_hComm == NULL)
	{
		//OutputLog::LOG("Simulator - Serial Port Close Sucess\n", OutputLog::LogLevel::System);
		return true;
	}
	else
	{
		//OutputLog::LOG("Simulator - Serial Port Close Fail\n", OutputLog::LogLevel::System);
		return false;
	}

}

bool SerialPort::PortConfigure(unsigned long BaudRate, unsigned char ByteSize, unsigned long fParity, unsigned char  Parity, unsigned char StopBits)
{
	if ((m_bPortReady = GetCommState(m_hComm, &m_dcb)) == 0)
		return false;
	else
	{
		m_dcb.BaudRate = BaudRate;
		m_dcb.ByteSize = ByteSize;
		m_dcb.Parity = (unsigned char)fParity;
		m_dcb.StopBits = StopBits;
		m_dcb.fBinary = true;
		m_dcb.fDsrSensitivity = false;
		m_dcb.fParity = fParity;
		m_dcb.fOutX = false;
		m_dcb.fInX = false;
		m_dcb.fNull = false;
		m_dcb.fAbortOnError = true;
		m_dcb.fOutxCtsFlow = false;
		m_dcb.fOutxDsrFlow = false;
		m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
		m_dcb.fDsrSensitivity = false;
		m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
		m_dcb.fOutxCtsFlow = false;

		m_bPortReady = SetCommState(m_hComm, &m_dcb);
		if (m_bPortReady == 0)
		{
			CloseHandle(m_hComm);
			return false;
		}

	}
	return true;
}

bool SerialPort::SetCommunicationTimeouts(unsigned long ReadIntervalTimeout, unsigned long ReadTotalTimeoutMultiplier,
	unsigned long ReadTotalTimeoutConstant, unsigned long WriteTotalTimeoutMultiplier,
	unsigned long WriteTotalTimeoutConstant)
{

	if ((m_bPortReady = GetCommTimeouts(m_hComm, &m_CommTimeouts)) == 0)
		return false;
	else
	{
		m_CommTimeouts.ReadIntervalTimeout = ReadIntervalTimeout;
		m_CommTimeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant;
		m_CommTimeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier;
		m_CommTimeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant;
		m_CommTimeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier;
		m_bPortReady = SetCommTimeouts(m_hComm, &m_CommTimeouts);

		if (m_bPortReady == 0)
		{
			CloseHandle(m_hComm);
			return false;
		}
		else
			return true;

	}

}
bool SerialPort::WritePortRegister(unsigned char* Register, int length)
{

	bool bStatus = false;
	unsigned long dwBytesWritten = 0;
	bStatus = WriteFile(m_hComm, &Register[0], length, &dwBytesWritten, NULL);
	return bStatus;
}
bool SerialPort::ReadPortRegister(unsigned char* Register)
{

	bool bStatus = false;
	unsigned long dwBytesRead;
	bStatus = ReadFile(m_hComm, &Register[0], PORT_COMMUNICATIONSIZE, &dwBytesRead, NULL);
	return bStatus;
}

위에 코드는 간단한 시리얼 포트 open/close와 read/write를 구현한 부분입니다.

테스트해보려면 main 함수에서 객체 선언해서 사용하시면 됩니다.

마무리

시리얼 통신은 하드웨어와 소프트웨어 측면에서 간단하면서도 다양한 응용 분야에서 활용되는 중요한 통신 방법입니다. 컴퓨터와 다양한 장치들 간의 데이터 교환과 제어에 필수적인 기술이니, 시리얼 통신에 대해 더 알아보고 활용해 보시면 좋을 것 같습니다.

 

 

반응형
반응형

Intro

안녕하세요. 이번에는 클래스 다이어그램 작성 방법에 대해 이야기하려고 합니다. 클래스 다이어그램은 소프트웨어 개발에서 중요한 시각적 도구로서 코드를 이해하고 설계하는 데 도움이 되는 매우 유용한 도구입니다. 

클래스 다이어그램

클래스 다이어그램(Class Diagram)

  • 시간에 따라 변하지 않는 시스템의 정적인 면을 보여주는 대표적인 UML 구조 다이어그램
  • 시스템의 일부 또는 전체의 구조를 나타낼 수 있다.
  • 의존 관계를 명확히 보게 해주며, 순환 의존이 발생하는 지점을 찾아내서 어떻게 순환고리를 깰 수 있을지 결정할 수 있게 해 준다.

클래스 구성

접근 제어자 리스트

  • Attribute와 Method 앞의 기호가 접근 제어자이다.
접근 제어자 표시 설명
private - 이 클래스에서 생성된 객체만 접근 가능
public + 어떤 클래스의 객체에서든 접근 가능
protected # 이 클래스와 상속 관계에 있는 하위 클래스의 객체들만 접근 가능
pakage ~ 동일 패키지에 있는 클래스의 객체들만 접근 가능

클래스 다이어그램 관계 표현

UML 표기

  1. 일반화 (Generalization)
  • 일반화는 일반적으로 상속 관계를 표시할 때 표기 (Is -A 관계)

Class ParentA(){
	//부모클래스
}
Class ChildB():ParentA
{
	//자식클래스B
}

Class ChildC():ParentA
{
	//자식클래스C
}

2. 실체화(Realization)

  • 실체화는 Interface를 자식 클래스에서 실제로 구현

보통 Interface는 클래스 이름에 I를 붙힘

interface ITest{ //인터페이스
public:
	public void DeviceSearch();
    public void DeviceManager();
    public void OpenDevice();
    public void CloseDevice();
}

public Test1 : ITest//인터페이스를 상속받으면 전부 구현 해야 됨
{
    public override void DeviceSearch()
    {
      Console.WriteLine("DeviceSearch");
    }
    public override void DeviceManager()
    {
      Console.WriteLine("DeviceManager");
    }
    public override void OpenDevice()
    {
      Console.WriteLine("OpenDevice");
    }
    public override void CloseDevice()
    {
      Console.WriteLine("CloseDevice");
    }


}

3. 의존 (Dependency)

  • 의존관계는 클래스 간 참조가 일어남을 말함
  • 메서드 내에서 다른 클래스의 객체를 생성하거나 사용을 말함

public class User
{

  private String name;
  privateint age;
  public String Name
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
    }
  }
public int Age
  {
    get
    {
      return age;
    }
    set
    {
      age= value;
    }
  }

}

public class Board
{
  private String name;
  private int age;
  
  User user = new User();
  user.Name = "박순영";
  user.Age = 19;

}

4. 연관( Association , Directed Association)

  • 클래스들이 개념상 서로 연결되었음을 나타냄. 보통은 한 클래스가 다른 클래스에서 제공하는 기능을 사용하는 상황일 때 표시
  • 연관 관계의 숫자 표현

– 1 - 1개의 표현

– * - 0 ~ n 개의 표현

– n... m : n부터 m까지 연관관계를 맺음

4.1 일반 연관(Association)

  • 다른 객체의 참조를 가지는 필드를 의미

public class User
{

  private String name;
  private int age;
  private Board board;
  public String Name
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
    }
  }
public int Age
  {
    get
    {
      return age;
    }
    set
    {
      age= value;
    }
  }

}



public class Board
{
  private String name;
  private int age;
  private List<user> users;
  
  public void Open()
  {
    ///
  }

}

4.2 직접 연관 (Directed Association)

  • 직접 연관 관계는 방향성을 갖는데, 방향성으로 참조하는 쪽과 참조당하는 쪽을 구분

public class User
{

  private String name;
  private int age;
  public String Name
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
    }
  }
public int Age
  {
    get
    {
      return age;
    }
    set
    {
      age= value;
    }
  }

}


public class Board
{
  private String name;
  private int age;
  private List<user> users;
  
  public void Open()
  {
    ///
  }

}

 

5.1 집합 (Aggregation)

  • 집약 관계는 한 객체가 다른 객체를 포함하는 것을 나타냄
  • 부분 객체를 다른 객체와 공유 가능
  • 전체 객체의 라이프타임과 부분 객체의 라이프타임은 독립적

5.2 집합 연관

  • 클래스 다이어그램에서 클래스 간의 관계 중 하나로, 한 클래스의 인스턴스가 다른 클래스의 인스턴스들과 집합 형태의 관계를 가지는 것을 의미
  • 한 클래스가 다른 클래스의 객체들을 소유하거나 포함하는 관계
class CPU
{
    public string Model { get; private set; }

    public CPU(string model)
    {
        Model = model;
    }
}

class MainBoard
{

    public string Model { get; private set; }

    public MainBoard(string model)
    {
        Model = model;
    }



}


// 컴퓨터(Mainboard) 클래스
class Computer
{
    private list<Mainboard> mb;
    private list<CPU> cpu;

    purlic Computer(list<Mainboard> MB, list<CPU> CPU)
  {
      mb = MB;
      cpu = CPU
  }

  
    
}

6.1 합성(Composition)

  • 부분 객체가 전체 객체에 속하는 관계
  • 전체 객체가 사라지면 부분 객체도 사라짐
  • 부분 객체를 다른 객체와 공유 불가
  • 부분 객체의 라이프타임은 전체 객체의 라이프타임에 의존

public class Computer
{
  private Mainboard mb;
  private CPU cpu;
  purlic Computer()
  {
      mb = new MainBoard();
      cpu = new CPU();
  }
}

6.2 복합 연관

  • 클래스 간의 관계 중 하나로, 한 클래스의 인스턴스가 다른 클래스의 인스턴스들과 부분-전체 관계를 가지는 것을 의미
  • 한 클래스의 객체가 다른 클래스의 객체들을 구성하는 관계를 나타냅니다. 이렇게 복합 연관을 가지는 클래스들은 하나의 객체가 여러 개의 다른 객체들을 포함하고 있으며, 이들 객체들은 함께 묶여서 하나의 논리적인 단위를 이룸

마무리

소프트웨어 개발은 협업과 이해를 기반으로 하기 때문에 명확하고 효과적인 클래스 다이어그램 작성은 개발자들 사이의 원활한 소통을 도와줍니다. 이상입니다.

반응형
반응형

Intro


안녕하세요. 이번에는 하드웨어 스레드 개수를 아는 방법에 대해 포스팅하겠습니다.

하드웨어 스레드 개수 알기


하드웨어 스레드 개수는 windows의 [작업 관리자] - [성능] 탭에서 확인이 가능합니다.

제 컴퓨터는 코어 4, 논리 프로세서 8개임을 알 수 있습니다. 일반적으로 프로그래밍을 할 때 (하드웨어 스레드 수 x 2) +1이라는 공식으로 나오는 수만큼 멀티 스레드를 만들면 좋다고 합니다. 이 공식으로 계산할 때 std::thread::hardware_concurrency()를 사용하면 좋습니다. 그리고 만약 std::thread::hardware_concurrency()를 사용할 수 없다면 0을 반환하게 됩니다.

코드

#include <iostream>
#include <thread>
int main(void)
{
    std::cout << "하드웨어 컨텍스트 수 : " << std::thread::hardware_concurrency() << std::endl;

    return 0;

}

결과

마무리


이상으로 포스팅 마치겠습니다. 감사합니다.

반응형

'[C++ STL]' 카테고리의 다른 글

[C++ STL - 스레드(thread)(1)]  (0) 2021.12.26
[C++ - vector Tuple sort 방법]  (0) 2021.11.16
[C++ For문에서 Vector erase 사용법  (0) 2021.11.01
[C++ STL - chrono(시간 측정)]  (0) 2021.06.30
[C++ STL - forward_list]  (0) 2021.06.24
반응형

Intro


안녕하세요. 이번에는 thread(스레드)에 대해서 포스팅하겠습니다. 고성능 프로그램을 만들 때는 멀티 코어를 잘 활용하느냐가 굉장히 중요합니다. 병렬 프로그래밍을 지원하기 위해 C++ 11에서 thread는 프로그래밍을 단순하게 하면서 플랫폼 독립적으로 구현이 가능합니다.

thread 만들기


간단하게 스레드를 만들어 보겠습니다.
코드

#include <iostream>
#include <thread>


int main(void)
{
    std::thread Thread1([]()
        {
            {
                for (int i = 0; i < 5; i++)
                    std::cout << "스레드 1 : " << i << std::endl;
            }
        });
    Thread1.join();
    return 0;

}

결과

Thread1.join()을 넣는 이유는 스레드가 아직 실ㅇ행 중인데 프로그램이 종료 되기 때문에 join함수를 사용하여 스레드의 실행이 끝날 떄까지 기다리게 한다.
다음은 여러개의 스레드를 돌렸을 때이다.
코드

#include <iostream>
#include <thread>


int main(void)
{
    std::thread Thread1([]()
        {
            {
                for (int i = 0; i < 5; i++)
                    std::cout << "스레드 1 : " << i << std::endl;
            }
        });


    std::thread Thread2([]()
        {
            {
                for (int i = 10; i < 15; i++)
                    std::cout << "스레드 2 : " << i << std::endl;
            }
        });


    std::thread Thread3([]()
        {
            {
                for (int i = 20; i < 25; i++)
                    std::cout << "스레드 3 : " << i << std::endl;
            }
        });

    Thread1.join();
    Thread2.join();
    Thread3.join();

    return 0;

}

결과

결과를 보니 제가 생각한 결과와 다르게 나왔습니다. 내 예상은 스레드 1이 끝나고 스레드 2가 시작될 줄 알았는데 결과가 뒤죽박죽 섞여 있습니다. 이유는 스레드가 동시에 시작되기 때문입니다. 스레드 1이 끝난 후 스레드 2가 실행되고 싶으면 스레드 1이 끝났을 때 join 함수를 넣어주면 해결이 됩니다.

코드

#include <iostream>
#include <thread>


int main(void)
{
    std::thread Thread1([]()
        {
            {
                for (int i = 0; i < 5; i++)
                    std::cout << "스레드 1 : " << i << std::endl;
            }
        });
    Thread1.join();

    std::thread Thread2([]()
        {
            {
                for (int i = 10; i < 15; i++)
                    std::cout << "스레드 2 : " << i << std::endl;
            }
        });
    Thread2.join();

    std::thread Thread3([]()
        {
            {
                for (int i = 20; i < 25; i++)
                    std::cout << "스레드 3 : " << i << std::endl;
            }
        });

    Thread3.join();

    return 0;

}

결과

결과를 보면 원하는 대로 스레드 1이 끝난 후 스레드 2가 실행되고 스레드 2가 끝난 후 스레드 3이 실행되었습니다.

마무리


이상으로 포스팅을 마치겠습니다. 다음 시간에는 스레드 식별자와 스레드 교환에 대한 포스팅을 하겠습니다.
감사합니다.

반응형

'[C++ STL]' 카테고리의 다른 글

[C++ Stl - 하드웨어 스레드 개수 알기]  (0) 2021.12.26
[C++ - vector Tuple sort 방법]  (0) 2021.11.16
[C++ For문에서 Vector erase 사용법  (0) 2021.11.01
[C++ STL - chrono(시간 측정)]  (0) 2021.06.30
[C++ STL - forward_list]  (0) 2021.06.24
반응형

Intro


안녕하세요, 오늘은 제가 오레일리의 고성능 파이썬이라는 책을 보다가, 모범적인 개발 절차에 대한 좋은 글을 보게되어서, 공유드리고자 글을 쓰게 되었습니다.

저도 주니어 개발자로서 부족함을 많이 느끼고 있는데요, 이 글에 쓰여져있는 내용을 잘 새겨듣고 실천하면서 실력을 기르려고 합니다.

문서화/ 좋은 구조/ 테스트


이 책에서는 모범적인 작업 절차의 핵심 요소가 문서화/ 좋은 구조/ 테스트라고 했는데요, 각각에 대해서 정리해보겠습니다.

문서화

문서화... 저도 회사에서 일하면서 느끼는 거지만 문서화 만큼 중요하면서 귀찮은 건 없는거 같습니다 ㅋㅋㅋ 하지만 지금이 아닌 나중을 위해서, 문서화는 꼭꼭 필요한 절차라고 생각합니다. 책의 저자는 프로젝트에 대한 설명을 README.md파일이나 docs/폴더에 적으면 좋다고 하는데요, 이 설명에 들어갈 내용은 아래와 같습니다.

  1. 프로젝트 목적
  2. 폴더 내용 (디렉토리 구조 및 용도)
  3. 데이터 출처
  4. 중요한 파일 목록
  5. 프로그램과 파일의 실행 방법
  6. 테스트 실행 방법

또한 코드의 모든 함수, 클래스, 모듈에 docstring을 추가하는 것도 좋다고 합니다. docstring에는 함수가 달성하고자 하는 내용과 예상 출력을 보여주는 간단한 예시를 적으라고 합니다. 저같은 경우는 로직이 복잡하거나 특수한 제약 사항에 의해서 코드가 어색해질 때 docstring을 추가하는데요, 모든 함수, 클래스, 모듈에 docstring을 추가하라니... 벌써부터 머리가 아프네요 ㅋㅋㅋ. 이런 docstring은 우리가 많이 쓰는 numpy가 정말 잘 되어 있는거 같아요.

아래는 PyCharm에서 numpy의 concatenate함수에 대한 docstring을 보여줍니다.

함수의 파라미터의 타입과 역할, 비슷한 함수 뿐만 아니라 함수 설명, 예시까지 정말 완벽한 docstring이라고 생각됩니다. 하지만 현업에서는 이런 걸 다 지키면서 일하기에는 무리가 있어 보이네요 ㅎㅎ

하지만 저도 저자가 말한 것처럼 일하면서 최대한 다른 사람들이 코드를 사용하고, 이해하기 쉽게하기 위해서 문서화에 더 신경을 써야할 거 같아요.

좋은 구조

저자는 프로젝트의 코드 작성 및 관리에 대해서도 여러 팁을 줍니다. 아래에 하나씩 열거해보고 제 생각을 적겠습니다.

  1. 코드는 짧게 만들어야 한다. 그러면 테스트하기도 쉽고, 이해하기도 쉽다.

    • 정말 맞는 말 같아요. 저도 회사에게 사수에게 한 함수는 반드시 하나의 일만 해야된다는 피드백을 자주 받았는데요, 각 함수가 하나의 일만 하도록 하다보니 코드 가독성이 좋아지는 거 같았어요.
  2. 소스 관리를 해라 (== git을 잘 사용해라). commit을 작은 단위로 자주해라

    • git의 중요성에 대해서는 말할 필요가 없는 거 같아요. 뒤에 commit을 작은 단위로 자주하라는 피드백은 공감가는게, 변경사항을 commit하지 않고 개발하다가 나중에 commit하려다 보면, 서로 관계없는 변경사항끼리 엉켜있어서 적절한 commit message를 사용하기 어렵더라고요. commit message는 디버그 및 코드 변경 히스토리를 파악하기 위해서 꼭 필요한 거 같아요!
  3. PEP8 코딩 표준을 지켜라 (feat. black, flake8, pylint, isort ...)

    • PEP8 스타일은 파이썬 프로그래밍에 있어서 기본이죠. 그리고 우리가 만든 코드가 PEP8에 맞춰 작성되었는지 확인해주는 여러 보조 라이브러리들이 있습니다.

    • black: 코드의 identation이 잘 되어있는지, 한 줄의 길이가 길진 않은지 등을 판단하고 적절하게 formatting을 해주는 라이브러리 입니다.

    • flake8, pylint: 코드를 lint한다고 하는데요, 코드에 문법상이나 스타일 상으로 문제가 있는지 등을 알려줍니다. 눈으로 발견하기 어려운 실수를 찾아줘서 좋은 거 같아요.

    • isort: 프로젝트가 커지다 보면 import하는게 많아질 때가 있잖아요? isort는 import를 알파벳순으로, 보기 좋게 formatting해주는 라이브러리 입니다.

    • 위와 같이 도움을 주는 여러 라이브러리가 있지만, 사람에 따라서 이를 사용하는 걸 선호하는 사람도 있고, 아니면 스스로 잘 지키도록 단련?하는게 중요하다고 하는 사람도 있는 거 같아요. 결론은 개취를 존중하자 ㅋㅋㅋ

  4. 운영체제와 분리된 환경을 만들어라

    • 프로젝트에 따라서 필요한 라이브러리나 버전이 다를 수 있죠. 그래서 프로젝트마다 독립된 환경을 만드는게 중요합니다. 가장 간단하고 많이 알려진 방법으로는 Anaconda 또는 pipenv를 통해서 가상환경을 만드는 방법이 있습니다.
    • 요즘 더 핫한 거는 docker를 이용해서 환경을 구성하는 방법같아요. 저도 잘은 모르지만, 위의 방법들 보다 강한? 독립성을 보장해주는 방법인 거 같습니다.
  5. 자동화해라

    • 자동화가 많이 하고 수동 작업을 줄일수록 실수할 여지는 적어진다고 합니다. CI/CD 자동화를 통해서 누구나 실행하고 지원할 수 있는 표준 절차를 만드는 것이 바람직하다고 하네요. 저에게는 아직 어려운 일인거 같아요 ㅜ

테스트

특정 입력에 대해서 코드 작성자가 예상한 출력이 나오는지 확인해보는 것을 테스트라고 합니다. 코드를 실제 서비스에 배포하기 전에, 이상이 없는지 확인하는 것이죠. 파이썬의 경우 unittest라는 내장 모듈을 제공하고, 이에 기반한 pytest도 있습니다. 테스트가 중요한만큼, 기존 코드에 테스트 코드가 없는 경우에는 반드시 추가를 해줘야한다고 합니다. 테스트 코드는 주로 tests/폴더에 작성하고 관리하는게 좋다고하네요. 검증이 필요한 부분부분을 테스트하는 코드를 통해, 최종적으로 프로젝트 전체 흐름을 검사하는 intergration test가 되야한다고 합니다. 테스트에 관해서는 저도 경험이 적어서 전달밖에 못하겠네요 ㅎㅎ.

아무튼 모든 코드가 내가 의도한 대로 작동하는지 확인하기 위해서는 테스트가 반드시 필요하니, 저도 pytest같은 모듈을 통해 테스트 코드를 작성하는 연습을 해봐야겠습니다.

마무리


오늘은 제가 공부하고 있는 책에 나온 모범적 작업 절차에 대해서 정리해봤습니다. 우리 모두 좋은 개발자가 되어봐요! 화이팅!

참고


고성능 파이썬

반응형

+ Recent posts