1. Trang chủ
  2. » Công Nghệ Thông Tin

slike bài giảng tính toán lưới - nguyễn hữu đức bài 4 truyền thông điểm điểm trong lập trình song song truyền thông điệp

54 483 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 54
Dung lượng 341,29 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Ch ươ ng trình deadlock v1 – Không b deadlock ị1... Ch ươ ng trình deadlock v21... Ch ươ ng trình deadlock v31... arrived=FALSE while arrived == FALSE { "work planned for processor to do

Trang 1

Truy n thông đi m đi m trong l p trình ề ể ể ậ

Trang 3

Ti n trình ngu n và ti n trình đích ế ồ ế

 Truy n thông đi m đi m là truy n thông hai phía ề ể ể ề

• Đòi h i kh i t o quá trình truy n thông t c hai phía ỏ ở ạ ề ừ ả

• G m m t ti n trình g i và m t ti n trình nh n ồ ộ ế ử ộ ế ậ

• Ti n trình g i g i là ti n trình ngu n ế ử ọ ế ồ

• Ti n trình nh n g i là ti n trình đích ế ậ ọ ế

Trang 5

C u trúc thông đi p ấ ệ

 G m 2 ph n:ồ ầ

• Thông tin v thông đi pề ệ

• N i dung thông đi pộ ệ

 Thông tin v thông đi p g m 4 ph n:ề ệ ồ ầ

• Ngu n: ti n trình g iồ ế ử

• Đích: ti n trình nh nế ậ

• Nhóm truy n thông: Nhóm ti n trình bao g m c ngu n và đích ề ế ồ ả ồ

• Tag: Dùng đ phân bi t v i các thông đi p khácể ệ ớ ệ

− Quan tr ngọ

− Cách dùng ph thu c t ng chụ ộ ừ ương trình

Trang 6

N i dung thông đi p ộ ệ

 N i dung thông đi p g m 3 ph n:ộ ệ ồ ầ

• B đ m: S lộ ế ố ượng d li u trong b đ m c n trao đ iữ ệ ộ ệ ầ ổ

− count: count * sizeof(dtype)

− S ph n t c a m ngố ầ ử ủ ả

Trang 7

Quá trình g i nh n thông đi p ử ậ ệ

 Quá trình g i thông đi pử ệ

• Ngu n (đ nh danh ngồ ị ườ ửi g i) là ng m đ nhầ ị

• Thông tin và n i dung c a thông đi p ph i độ ủ ệ ả ược khai báo rõ ràng

b i ti n trình g iở ế ử

 Thông đi p treo (a pending message)ệ

• Thông đi p đã g i nh ng ch a đệ ử ư ư ược nh nậ

• Không đượ ưc l u trong hàng đ iợ

• Ch a các thu c tính ph c v quá trình nh nứ ộ ụ ụ ậ

Trang 8

Qúa trình g i nh n thông đi p ử ậ ệ

 Quá trình nh n thông đi pậ ệ

• Ch đ nh thông tin thông đi p đ so kh p v i các thông đi p treoỉ ị ệ ể ớ ớ ệ

• Thành công: thông đi p đệ ược nh n, quá trình nh n k t thúcậ ậ ế

• Không thành công: ti p t c ch đ i, so kh p, quá trình nh n ch a ế ụ ờ ợ ớ ậ ưhoàn thành

• Cung c p đ không gian l u tr cho n i dung thông đi pấ ủ ư ữ ộ ệ

Trang 9

G i nh n thông đi p có ràng bu c ử ậ ệ ộ

 Dùng hai đ nh tuy n (routine)ị ế

• MPI_Send: g i thông đi pử ệ

• MPI_Recv: nh n thông đi pậ ệ

 C hai đ nh tuy n đ u ràng bu c v i ti n trình g i nóả ị ế ề ộ ớ ế ọ

 S ràng bu c k t thúc khi quá trình truy n thông hoàn thànhự ộ ế ề

 Khi nào hoàn thành truy n thông?ề

 Hi n tệ ượng deadlock có t n t i?ồ ạ

Trang 11

Đ nh tuy n MPI_Send (ti p) ị ế ế

MPI_Send(void* buf, int count, MPI_Datatype dtype, int dest,

Truy n thông đi p trong ề ệ buf đ n ti n trình ế ế dest

Giá tr tr v c a hàm là ị ả ề ủ mã l iỗ

IN buf bi n con tr (không ế ỏ

đ nh ki u)ị ể tr đ n vùng nh ch a d li uệỏ ế ớ ứ ữ

IN count int s lố ượng ph n t trong d ầ ử ữ

li uệ

IN dtype MPI_Datatype ki u d li uể ữ ệ

trình g i và nh nử ậ

Trang 12

Thông tin thông đi p (destination đ ệ ượ c hi u ng m ể ầ

đ nh) - đ ị ể so kh p v i thông đi p treoớ ớ ệ

status  Thông tin v thông đi p đã nh n ề ệ ậ

Đ nh tuy n MPI_Recv ị ế

Giá tr c a tag, source có th là các ký t thay th ị ủ ể ự ế

Trang 13

MPI_Recv(void* buf, int count, MPI_Datatype dtype, int source,

Nh n truy n thông đi p t ậ ề ệ ừ source đ a vào ư buf

Giá tr tr v c a hàm là ị ả ề ủ mã l iỗ

OUT buf Bi n con tr (không ế ỏ

đ nh ki u)ị ể Tr đ n vùng nh ch a d li uệỏ ế ớ ứ ữ

IN count int S lố ượng ph n t trong d ầ ử ữ

li uệ

IN dtype MPI_Datatype ki u d li uể ữ ệ

trình g i và nh nử ậOUT status MPI_Status Thông tin v thông đi p đã ề ệ

nh nậ

Trang 14

M t s l u ý quan tr ng v đ nh tuy n MPI_Recv ộ ố ư ọ ề ị ế

• N u thông đi p nh n đế ệ ậ ược có s lố ượng ph n t l n h n giá tr ầ ử ớ ơ ịcount, s phát sinh l i.ẽ ỗ

• Ti n trình g i và nh n ph i đ ng ý v i nhau v lo i d li u truy n ế ử ậ ả ồ ớ ề ạ ữ ệ ềthông N u không, k t qu là không xác đ nh (MPI không ki m tra ế ế ả ị ể

được chính xác d li u)ữ ệ

• Khi đ nh tuy n tr v giá trị ế ả ề ị

− D li u nh n đã đữ ệ ậ ược chuy n vào b đ m;ể ộ ệ

− Đ i s status cho bi t giá tr các tham s source, tag, và s ồ ố ế ị ố ố

lượng d li u th c s nh n đữ ệ ự ự ậ ược

Trang 15

Ví d 1 – Truy n thông đi m đi m ụ ề ể ể

1 /* simple send and receive */

9 MPI_Init(&argc, &argv); /* Initialize MPI */

10 MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */

Trang 16

Ví d 1 – Truy n thông đi m đi m ụ ề ể ể

11 if( myrank == 0 ){ /* Send a message */

12 for (i=0;i<100;++i) a[i]=sqrt(i);

13 MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

14 }

15 else if( myrank == 1 ) /* Receive a message */

16 MPI_Recv( b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD,

&status );

17 MPI_Finalize(); /* Terminate MPI */

18 }

Trang 17

mpicc comm_pp.c –o comm_pp -lmBiên d ch: ị

Ví d 1 – Truy n thông đi m đi m ụ ề ể ể

Trang 18

Ký t thay th , bi n status ự ế ế

 Ti n trình nh n đế ậ ược phép nh n d li u t ti n trình g i b t kỳ v i tag ậ ữ ệ ừ ế ử ấ ớ

b t kỳ.ấ

 B t kỳ ngu n nào: MPI_ANY_SOURCEấ ồ

 B t kỳ tag nào: MPI_ANY_TAGấ

 Có th dùng ký t thay th cho ngu n ho c tag ho c c haiể ự ế ồ ặ ặ ả

Trang 20

Ví d 2 – Truy n thông đi m đi m ụ ề ể ể

8 MPI_Init(&argc, &argv); /* Initialize MPI */

9 MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */

Trang 21

Ví d 2 – Truy n thông đi m đi m ụ ề ể ể

10 if( myrank == 0 ){ /* Send a message */

11 for (i=0;i<100;++i) a[i]=sqrt(i);

12 MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

13 }

14 else if( myrank == 1 ){ /* Receive a message */

15 MPI_Recv( b, 300, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD,

&status );

16 MPI_Get_count(&status,MPI_DOUBLE,&count);

17 printf("P:%d message came from rank %dn", myrank, status.MPI_SOURCE);

18 printf("P:%d message had tag %dn",myrank,status.MPI_TAG);

19 printf("P:%d message size was %dn",myrank,count);

20 }

21 MPI_Finalize(); /* Terminate MPI */

22 }

Trang 22

Ví d 2 – Truy n thông đi m đi m ụ ề ể ể

10 if( myrank == 0 ){ /* Send a message */

11 for (i=0;i<100;++i) a[i]=sqrt(i);

12 MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

13 }

14 else if( myrank == 1 ){ /* Receive a message */

15 MPI_Recv( b, 300, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD,

&status );

16 MPI_Get_count(&status,MPI_DOUBLE,&count);

17 printf("P:%d message came from rank %dn", myrank, status.MPI_SOURCE);

18 printf("P:%d message had tag %dn",myrank,status.MPI_TAG);

19 printf("P:%d message size was %dn",myrank,count);

20 }

21 MPI_Finalize(); /* Terminate MPI */

22 }

Output:

P:1 message came from rank 0

P:1 message had tag 17

P:1 message size was 100

Trang 23

Tr ng thái th i gian ch y ạ ờ ạ

 Khi đ nh tuy n MPI_Send đị ế ược g i, x y ra 1 trong 2 trọ ả ường h p sau:ợ

• TH1: Thông đi p đệ ượ ưc l u vào b đ m riêng c a MPI, và độ ệ ủ ược

truy n t i đích sau, trong m t ti n trình ng m nào đó Ti n trình g i ề ớ ộ ế ầ ế ử

được phép chuy n sang l nh khác ngay sau khi thông đi p chuy n ể ệ ệ ể

h t vào b đ m.ế ộ ệ

• TH2: Thông đi p v n n m t i n i nó đệ ẫ ằ ạ ơ ược g i, dọ ướ ại d ng các bi n ế

c a chủ ương trình cho đ n khi ti n trình đích s n sàng nh n.ế ế ẵ ậ

 Th t ng c nhiên khi ngay c trong trậ ạ ả ường h p 1, l i g i MPI_Send có th ợ ờ ọ ể

tr v giá tr ả ề ị tr ướ c khi b t kỳ ấ l i g i không ph i c c b ờ ọ ả ụ ộ nào đó được b t ắ

đ u.ầ

Trang 24

 S hoàn thành c a đ nh tuy n MPI_Recv là đ n gi n và tr c quan:ự ủ ị ế ơ ả ự

• Khi so kh p đúng thông đi p, d li u đớ ệ ữ ệ ược chuy n t i đ i s đ u ra ể ớ ố ố ầ

c a l i g iủ ờ ọ

• Ngay sau đó, các bi n ch a thông đi p trong MPI_Recv s n sàng ế ứ ệ ẵdùng cho l i g i khácờ ọ

Trang 25

S ràng bu c và s hoàn thành (ti p) ự ộ ự ế

 S hoàn thành c a đ nh tuy n MPI_Send là ự ủ ị ế đ n gi nơ ả , nh ng không ư

tr c quan:ự

• MPI_Send hoàn thành khi:

− Thông đi p trong l i g i không còn liên quan đ n MPIệ ờ ọ ế

− V nguyên t c, hoàn thành ngay sau khi thông đi p đề ắ ệ ược đ a ư

h t vào b đ m, th m chí thông đi p ch a b gi i ph ng kh i ế ộ ệ ậ ệ ư ị ả ỏ ỏ

ti n trình g iế ử

Trang 26

− B đ m lúc này không th dùng độ ệ ể ược

− Thông đi p trong b đ m s chi m d không gian b đ m cho ệ ộ ệ ẽ ế ữ ộ ệ

đ n khi ti n trình đích b t đ u nh n thông đi p ho c khi b ế ế ắ ầ ậ ệ ặ ộ

đ m đ kích thệ ủ ướ ưc l u trữ

Trang 28

Hi n t ệ ượ ng Deadlock

 DeadLock (b t c): là tình tr ng hai hay nhi u ti n trình cùng ch đ i ế ắ ạ ề ế ờ ợ

m t s ki n nào đó x y ra N u không có s tác đ ng t bên ngoài thì ộ ự ệ ả ế ự ộ ừ

s ch đ i là vô h nự ờ ợ ạ

 Qúa trình g i nh n có ràng bu c có th d n đ n hi n tử ậ ộ ể ẫ ế ệ ượng deadlock

Trang 29

Ví d 2 – Ch ụ ươ ng trình Deadlock

1 if( myrank == 0 ) { /* Receive, then send a message */

2 MPI_Recv(b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );

3 MPI_Send(a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

5 else if( myrank == 1 ) { /* Receive, then send a message */

6 MPI_Recv(b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status );

7 MPI_Send(a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );

9 MPI_Finalize(); /* Terminate MPI */

Trang 30

Ch ươ ng trình deadlock v1 – Không b deadlock ị

1 if( myrank == 0 ) { /* Receive a message, then send one */

2 MPI_Recv(b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );

3 MPI_Send(a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

5 else if( myrank == 1 ) { /* Send a message, then receive one */

6 MPI_Send(a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );

7 MPI_Recv(b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status );

9 MPI_Finalize(); /* Terminate MPI */

10 }

Trang 31

Ch ươ ng trình deadlock v2

1 if( myrank == 0 ) { /* Receive a message, then send one */

2 MPI_Send(a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

3 MPI_Recv(b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );

5 else if( myrank == 1 ) { /* Send a message, then receive one */

6 MPI_Send(a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );

7 MPI_Recv(b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status );

Trang 32

Ch ươ ng trình deadlock v3

1 #define N 100000000;

2 if( myrank == 0 ) { /* Receive a message, then send one */

3 MPI_Send(a, N, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

4 MPI_Recv(b, N, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );

6 else if( myrank == 1 ) { /* Send a message, then receive one */

7 MPI_Recv(b, N, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status );

8 MPI_Send(a, N, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );

10.

Trang 33

Tránh hi n t ệ ượ ng deadlock

 Phân tích thi t k chế ế ương trình phù h pợ

 T ch c chổ ứ ương trình không ph thu c kích thụ ộ ước b đ m c a MPIộ ệ ủ

 Có th debug chể ương trình song song b ng các công c h tr nh ằ ụ ỗ ợ ư

ch c năng debug c a ptp, hay m t s công c hi n th tr c quan khác,ứ ủ ộ ố ụ ể ị ự

 S d ng ch đ g i nh n không ràng bu cử ụ ế ộ ử ậ ộ

Trang 34

Truy n thông không ràng bu c ề ộ

 Th c thi các đ nh tuy n g i, nh n mà không khóa ti n trình g i nó.ự ị ế ử ậ ế ọ

 Tách quá trình kh i t o và hoàn thành thành hai l i g i MPI khác nhau.ở ạ ờ ọ

• Kh i t o quá trình g i/nh nở ạ ử ậ

• Hoàn thành quá trình g i/nh nử ậ

 Gi a hai l i g i, chữ ờ ọ ương trình có th th c hi n các đ nh tuy n khác.ể ự ệ ị ề

 Truy n thông t ng th p là gi ng nhau, m c dù giao di n c a th vi n là ề ầ ấ ố ặ ệ ủ ư ệkhác nhau

 Truy n thông ràng bu c và không ràng bu c có th dùng l n v i nhau.ề ộ ộ ể ẫ ớ

Trang 35

Kh i t o, hoàn thành, trình đi u khi n ở ạ ề ể

• Ki m tra xem quá trình đã hoàn thành hay ch aể ư

• Đ i cho đ n khi hoàn thànhợ ế

 Trình đi u khi n:ề ể

• Luôn được tr v b i các đ nh tuy n g i/nh n không ràng bu cả ề ở ị ề ử ậ ộ

• Dùng đ tham chi u đ n quá trình g i/nh n đã kh i t o.ể ế ế ử ậ ở ạ

Trang 36

MPI_Isend(void *buf, int count, MPI_Datatype dtype, int dest,

Không đ c/ghi bi n nào trong l i g i trọ ế ờ ọ ước giai đo n hoàn thànhạ

IN buf bi n con tr (không ế ỏ

đ nh ki u)ị ể tr đ n vùng nh ch a d li uệỏ ế ớ ứ ữ

IN count int s lố ượng ph n t trong d ầ ử ữ

li uệ

IN dtype MPI_Datatype ki u d li uể ữ ệ

trình g i và nh nử ậOUT Request MPI_Request Đ nh danh trình đi u khi nị ề ể

Trang 37

Đ nh tuy n kh i t o MPI_Irecv ị ế ở ạ

MPI_Irecv(void* buf, int count, MPI_Datatype dtype, int source,

Không đ c/ghi bi n nào trong l i g i trọ ế ờ ọ ước giai đo n hoàn thànhạ

OUT buf Bi n con tr (không ế ỏ

đ nh ki u)ị ể Tr đ n vùng nh ch a d li uệỏ ế ớ ứ ữ

IN count int S lố ượng ph n t trong d ầ ử ữ

li uệ

IN dtype MPI_Datatype ki u d li uể ữ ệ

trình g i và nh nử ậOUT request MPI_Request Đ nh danh trình đi u khi nị ề ể

Trang 38

 Bi n request: xác đ nh ti n trình kh i t o g i/nh nế ị ế ở ạ ử ậ

 MPI_Wait tr v đi u khi n khi ti n trình kh i t o g i/nh n hoàn thànhả ề ề ể ế ở ạ ử ậ

 Bi n status:ế

• Đ nh tuy n kh i t o g i: mã l i cho quá trình g iị ế ở ạ ử ỗ ử

• Đ nh tuy n kh i t o nh n: thông tin c a thông đi p nh n.ị ế ở ạ ậ ủ ệ ậ

Đ nh tuy n hoàn thành: MPI_Wait ị ế

int MPI_Wait(MPI_Request *request, MPI_Status* status)

Trang 39

 Bi n request: xác đ nh ti n trình kh i t o g i/nh nế ị ế ở ạ ử ậ

 MPI_Test tr v đi u khi n ngay khi g i xong.ả ề ề ể ọ

 Bi n flag:ế

• true: đ nh tuy n kh i t o đã hoàn thànhị ế ở ạ

• false: đ nh tuy n kh i t o ch a hoàn thànhị ế ở ạ ư

 Bi n status: khi (flag == true)ế

• Đ nh tuy n kh i t o g i: mã l i cho quá trình g iị ế ở ạ ử ỗ ử

• Đ nh tuy n kh i t o nh n: thông tin c a thông đi p nh n.ị ế ở ạ ậ ủ ệ ậ

Đ nh tuy n hoàn thành: MPI_Test ị ế

int MPI_Test(MPI_Request *request, int *flag,

MPI_Status* status)

Trang 40

Gi m tr cho h th ng m ng ả ễ ệ ố ạ

MPI_IRECV( ,request)

arrived=FALSE

while (arrived == FALSE) {

"work planned for processor to do while waiting for message data“

MPI_TEST(request,arrived,status)

}

"work planned for processor to do with the message

data"

Trang 41

Ví d 3 – Truy n thông không ràng bu c ụ ề ộ

9 MPI_Init(&argc, &argv); /* Initialize MPI */

10 MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */

Trang 42

Ví d 3 – Truy n thông không ràng bu c ụ ề ộ

1 /* deadlock avoided */

2 if( myrank == 0 ) { /* Post a receive, send a message, then wait */

3 MPI_Irecv( b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &request );

4 MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );

5 MPI_Wait( &request, &status );

6 } else if( myrank == 1 ) { /* Post a receive, send a message, then wait */

7 MPI_Irecv( b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &request );

8 MPI_Send( a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );

9 MPI_Wait( &request, &status );

11 MPI_Finalize(); /* Terminate MPI */

12 }

Trang 44

Case study: Tìm ki m song song ế

 L p trình đ m s l n xu t hi n c a m t khoá (key) trong m t dãy cho ậ ế ố ầ ấ ệ ủ ộ ộ

trước, s d ng truy n thông đi m-đi mử ụ ề ể ể

 Dãy s cho trố ước đượ ưc l u trong m t file text data.in g m N ph n t có ộ ồ ầ ử

đ nh d ng :ị ạ

 S _ph n t _Nố ầ ử

 Ph n_t _th _1 ph n_t _th _2 ph n_t _th _Nầ ử ứ ầ ử ứ ầ ử ứ

 Các ph n t phân bi t b ng kho ng tr ng.ầ ử ệ ằ ả ắ

 Yêu c u ch n s ti n trình th c hi n là ầ ọ ố ế ự ệ ước c a s ph n t trong dãy.ủ ố ầ ử

 Khoá c n tìm ki m đầ ế ược truy n vào dề ướ ại d ng tham s c a chố ủ ương trình Ví d :ụ

 $ mpirun -np 4 program 23

Trang 45

Case study: Tìm ki m song song ế

 Thi t k chế ế ương trình

• Ti n trình g c (rank = 0)ế ố

• Đ c d li u vào t fileọ ữ ệ ừ

− Xác đ nh s ti n trình tham gia np, s ph n t c a m i mi n.ị ố ế ố ầ ử ủ ỗ ề

− Chia mi n tính toán thành np mi n conề ề

− G i d li u các mi n con cho các ti n trình tử ữ ệ ề ế ương ng.ứ

− Tìm ki m trên mi n con mà nó đ m nhi mế ề ả ệ

− Nh n k t qu g i v t các ti n trình con.ậ ế ả ử ề ừ ế

− Tính t ng s l n xu t hi n khoá key.ổ ố ầ ấ ệ

− In k t qu ra màn hình.ế ả

Ngày đăng: 24/10/2014, 11:00

TỪ KHÓA LIÊN QUAN

TRÍCH ĐOẠN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm