顯示具有 平行處理 標籤的文章。 顯示所有文章
顯示具有 平行處理 標籤的文章。 顯示所有文章

2015年11月30日 星期一

MPI Three-Group Pipeline

底下的MPI範例很有趣, 來自於5.6.3. Inter-Communication Examples
它主要是想要介紹建立三個節點, 彼此之間使用communicator串起來, 模擬成pipeline的運作方式.
希望產的效果如下圖:

程式碼我有動過, 如下
//http://www.mpi-forum.org/docs/mpi-1.1/mpi-11-html/node114.html
//Groups 0 and 1 communicate. Groups 1 and 2 communicate.
//Therefore, group 0 requires one inter-communicator, group 1 requires two inter-communicators,
//and group 2 requires 1 inter-communicator.

//int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm)
//int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv){
        MPI_Comm   myComm;       /* intra-communicator of local sub-group */
        MPI_Comm   myFirstComm;  /* inter-communicator */
        MPI_Comm   mySecondComm; /* second inter-communicator (group 1 only) */
        int membershipKey = 0, rank =0, buffer = 0;
        MPI_Status status;
        double start_time, recive_time;

        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);

        /* User code must generate membershipKey in the range [0, 1, 2] */
        membershipKey = rank % 3;
        start_time = MPI_Wtime();

        /* Build intra-communicator for local sub-group */
        MPI_Comm_split(MPI_COMM_WORLD, membershipKey, rank, &myComm);

        /* Build inter-communicators.  Tags are hard-coded. */
        if (membershipKey == 0){
                /* Group 0 communicates with group 1. */
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 1, 1, &myFirstComm);
        }
        else if (membershipKey == 1){
                /* Group 1 communicates with groups 0 and 2. */
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 0, 1, &myFirstComm);
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 2, 12, &mySecondComm);
        }
        else if (membershipKey == 2){
                /* Group 2 communicates with group 1. */
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 1, 12, &mySecondComm);
        }

        switch(membershipKey){
                case 0:
                        buffer = 100;
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        MPI_Send(&buffer, 1, MPI_INT, 0, 0, myFirstComm);
                        MPI_Recv(&buffer, 1, MPI_INT, 0, 0, myFirstComm, &status);
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        break;
                case 1:
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        MPI_Recv(&buffer, 1, MPI_INT, 0, 0, myFirstComm, &status);
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        buffer = 200;
                        MPI_Send(&buffer, 1, MPI_INT, 0, 0, myFirstComm);
                        MPI_Send(&buffer, 1, MPI_INT, 0, 0, mySecondComm);
                        break;
                case 2:
                        MPI_Recv(&buffer, 1, MPI_INT, 0, 0, mySecondComm, &status);
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        break;
        }

        MPI_Comm_free(&myComm);
        switch(membershipKey){/* free communicators appropriately */
                case 1:
                        MPI_Comm_free(&mySecondComm);
                        MPI_Comm_free(&myFirstComm);
                        break;
                case 0:
                        MPI_Comm_free(&myFirstComm);
                        break;
                case 2:
                        MPI_Comm_free(&mySecondComm);
                        break;
        }
        MPI_Finalize();
}
執行的結果如下
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
[0] Ending MPI_Init
[0] Starting MPI_Comm_rank...
[0] Ending MPI_Comm_rank
[0] Starting MPI_Comm_split...
[0] Ending MPI_Comm_split
[0] Starting MPI_Intercomm_create...
[0] Ending MPI_Intercomm_create
[0][0.000326]buffer=100
[0] Starting MPI_Send with count = 1, dest = 0, tag = 0...
[0] Ending MPI_Send
[0] Starting MPI_Recv with count = 1, source = 0, tag = 0...
[0] Ending MPI_Recv from 0 with tag 0
[0][0.000408]buffer=200
[0] Starting MPI_Comm_free...
[1] Ending MPI_Init
[1] Starting MPI_Comm_rank...
[1] Ending MPI_Comm_rank
[1] Starting MPI_Comm_split...
[1] Ending MPI_Comm_split
[1] Starting MPI_Intercomm_create...
[1] Ending MPI_Intercomm_create
[1] Starting MPI_Intercomm_create...
[1] Ending MPI_Intercomm_create
[1][0.000166]buffer=0
[1] Starting MPI_Recv with count = 1, source = 0, tag = 0...
[1] Ending MPI_Recv from 0 with tag 0
[1][0.000214]buffer=100
[1] Starting MPI_Send with count = 1, dest = 0, tag = 0...
[1] Ending MPI_Send
[1] Starting MPI_Send with count = 1, dest = 0, tag = 0...
[1] Ending MPI_Send
[1] Starting MPI_Comm_free...
[1] Ending MPI_Comm_free
[1] Starting MPI_Comm_free...
[2] Ending MPI_Init
[2] Starting MPI_Comm_rank...
[2] Ending MPI_Comm_rank
[2] Starting MPI_Comm_split...
[2] Ending MPI_Comm_split
[2] Starting MPI_Intercomm_create...
[2] Ending MPI_Intercomm_create
[0] Ending MPI_Comm_free
[0] Starting MPI_Comm_free...
[0] Ending MPI_Comm_free
[0] Starting MPI_Finalize...
[0] Ending MPI_Finalize
[1] Ending MPI_Comm_free
[1] Starting MPI_Comm_free...
[1] Ending MPI_Comm_free
[1] Starting MPI_Finalize...
[2] Starting MPI_Recv with count = 1, source = 0, tag = 0...
[2] Ending MPI_Recv from 0 with tag 0
[2][0.000409]buffer=200
[2] Starting MPI_Comm_free...
[2] Ending MPI_Comm_free
[2] Starting MPI_Comm_free...
[2] Ending MPI_Comm_free
[2] Starting MPI_Finalize...
[1] Ending MPI_Finalize
[2] Ending MPI_Finalize

2015年11月28日 星期六

MPI_Bcast

MPI_Bcast廣播函式, 這個是一個很有趣的功能. 將要變更的資料變數及內容傳送給其它的接收

/* C Example */
#include <mpi.h>
#include <stdio.h>

int main (int argc, char* argv[]){
        int rank, size;
        double t1;
        void *v;
        int flag;
        int mytable[1] = { 0 };

        MPI_Init (&argc, &argv);      /* starts MPI */
        MPI_Comm_rank (MPI_COMM_WORLD, &rank);        /* get current process id */
        MPI_Comm_size (MPI_COMM_WORLD, &size);        /* get number of processes */
        t1 = MPI_Wtime();
        MPI_Attr_get( MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag );
        printf( "Hello world from process %d of %d, time = %f, global time = %d\n", rank, size, MPI_Wtime() - t1, flag);

        mytable[0] = rank + 100;
        MPI_Barrier(MPI_COMM_WORLD);
        MPI_Bcast(&mytable[0], 1, MPI_INT, atoi(argv[1]), MPI_COMM_WORLD);
        printf("%d/%d: mytable[0] = %d\n", rank, size, mytable[0]);
        MPI_Barrier(MPI_COMM_WORLD);

        MPI_Finalize();
        return 0;
}
mpirun -np 5 ./bcast 0執行結果1
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
[0] Ending MPI_Init
[0] Starting MPI_Comm_rank...
[0] Ending MPI_Comm_rank
[0] Starting MPI_Comm_size...
[0] Ending MPI_Comm_size
[0] Starting MPI_Attr_get...
[0] Ending MPI_Attr_get
Hello world from process 0 of 5, time = 0.000011, global time = 1
[0] Starting MPI_Barrier...
[0] Ending MPI_Barrier
[0] Starting MPI_Bcast...
[0] Starting MPI_Bcast with count = 1
[0] Ending MPI_Bcast
0/5: mytable[0] = 100
[0] Starting MPI_Barrier...
[0] Ending MPI_Barrier
[0] Starting MPI_Finalize...
[0] Ending MPI_Finalize
[1] Ending MPI_Init
[1] Starting MPI_Comm_rank...
[1] Ending MPI_Comm_rank
[1] Starting MPI_Comm_size...
[1] Ending MPI_Comm_size
[1] Starting MPI_Attr_get...
[1] Ending MPI_Attr_get
Hello world from process 1 of 5, time = 0.000012, global time = 1
[1] Starting MPI_Barrier...
[1] Ending MPI_Barrier
[1] Starting MPI_Bcast...
[1] Starting MPI_Bcast with count = 1
[1] Ending MPI_Bcast
1/5: mytable[0] = 100
[1] Starting MPI_Barrier...
[1] Ending MPI_Barrier
[1] Starting MPI_Finalize...
[1] Ending MPI_Finalize
[2] Ending MPI_Init
[2] Starting MPI_Comm_rank...
[2] Ending MPI_Comm_rank
[2] Starting MPI_Comm_size...
[2] Ending MPI_Comm_size
[2] Starting MPI_Attr_get...
[2] Ending MPI_Attr_get
Hello world from process 2 of 5, time = 0.000012, global time = 1
[2] Starting MPI_Barrier...
[2] Ending MPI_Barrier
[2] Starting MPI_Bcast...
[2] Starting MPI_Bcast with count = 1
[2] Ending MPI_Bcast
2/5: mytable[0] = 100
[2] Starting MPI_Barrier...
[2] Ending MPI_Barrier
[2] Starting MPI_Finalize...
[3] Ending MPI_Init
[3] Starting MPI_Comm_rank...
[3] Ending MPI_Comm_rank
[3] Starting MPI_Comm_size...
[3] Ending MPI_Comm_size
[3] Starting MPI_Attr_get...
[3] Ending MPI_Attr_get
Hello world from process 3 of 5, time = 0.000010, global time = 1
[3] Starting MPI_Barrier...
[3] Ending MPI_Barrier
[3] Starting MPI_Bcast...
[3] Starting MPI_Bcast with count = 1
[3] Ending MPI_Bcast
3/5: mytable[0] = 100
[3] Starting MPI_Barrier...
[3] Ending MPI_Barrier
[3] Starting MPI_Finalize...
[4] Ending MPI_Init
[4] Starting MPI_Comm_rank...
[4] Ending MPI_Comm_rank
[4] Starting MPI_Comm_size...
[4] Ending MPI_Comm_size
[4] Starting MPI_Attr_get...
[4] Ending MPI_Attr_get
Hello world from process 4 of 5, time = 0.000009, global time = 1
[4] Starting MPI_Barrier...
[4] Ending MPI_Barrier
[4] Starting MPI_Bcast...
[4] Starting MPI_Bcast with count = 1
[4] Ending MPI_Bcast
4/5: mytable[0] = 100
[4] Starting MPI_Barrier...
[4] Ending MPI_Barrier
[4] Starting MPI_Finalize...
[2] Ending MPI_Finalize
[3] Ending MPI_Finalize
[4] Ending MPI_Finalize
mpirun -np 5 ./bcast 1執行結果2
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
[0] Ending MPI_Init
[0] Starting MPI_Comm_rank...
[0] Ending MPI_Comm_rank
[0] Starting MPI_Comm_size...
[0] Ending MPI_Comm_size
[0] Starting MPI_Attr_get...
[0] Ending MPI_Attr_get
Hello world from process 0 of 5, time = 0.000017, global time = 1
[0] Starting MPI_Barrier...
[0] Ending MPI_Barrier
[0] Starting MPI_Bcast...
[0] Starting MPI_Bcast with count = 1
[0] Ending MPI_Bcast
0/5: mytable[0] = 101
[0] Starting MPI_Barrier...
[0] Ending MPI_Barrier
[0] Starting MPI_Finalize...
[1] Ending MPI_Init
[1] Starting MPI_Comm_rank...
[1] Ending MPI_Comm_rank
[1] Starting MPI_Comm_size...
[1] Ending MPI_Comm_size
[1] Starting MPI_Attr_get...
[1] Ending MPI_Attr_get
Hello world from process 1 of 5, time = 0.000010, global time = 1
[1] Starting MPI_Barrier...
[1] Ending MPI_Barrier
[1] Starting MPI_Bcast...
[1] Starting MPI_Bcast with count = 1
[1] Ending MPI_Bcast
1/5: mytable[0] = 101
[1] Starting MPI_Barrier...
[1] Ending MPI_Barrier
[1] Starting MPI_Finalize...
[1] Ending MPI_Finalize
[2] Ending MPI_Init
[2] Starting MPI_Comm_rank...
[2] Ending MPI_Comm_rank
[2] Starting MPI_Comm_size...
[2] Ending MPI_Comm_size
[2] Starting MPI_Attr_get...
[2] Ending MPI_Attr_get
Hello world from process 2 of 5, time = 0.000008, global time = 1
[2] Starting MPI_Barrier...
[2] Ending MPI_Barrier
[2] Starting MPI_Bcast...
[2] Starting MPI_Bcast with count = 1
[2] Ending MPI_Bcast
2/5: mytable[0] = 101
[2] Starting MPI_Barrier...
[2] Ending MPI_Barrier
[2] Starting MPI_Finalize...
[3] Ending MPI_Init
[3] Starting MPI_Comm_rank...
[3] Ending MPI_Comm_rank
[3] Starting MPI_Comm_size...
[3] Ending MPI_Comm_size
[3] Starting MPI_Attr_get...
[3] Ending MPI_Attr_get
Hello world from process 3 of 5, time = 0.000008, global time = 1
[3] Starting MPI_Barrier...
[3] Ending MPI_Barrier
[3] Starting MPI_Bcast...
[3] Starting MPI_Bcast with count = 1
[3] Ending MPI_Bcast
3/5: mytable[0] = 101
[3] Starting MPI_Barrier...
[3] Ending MPI_Barrier
[3] Starting MPI_Finalize...
[4] Ending MPI_Init
[4] Starting MPI_Comm_rank...
[4] Ending MPI_Comm_rank
[4] Starting MPI_Comm_size...
[4] Ending MPI_Comm_size
[4] Starting MPI_Attr_get...
[4] Ending MPI_Attr_get
Hello world from process 4 of 5, time = 0.000009, global time = 1
[4] Starting MPI_Barrier...
[4] Ending MPI_Barrier
[4] Starting MPI_Bcast...
[4] Starting MPI_Bcast with count = 1
[4] Ending MPI_Bcast
4/5: mytable[0] = 101
[4] Starting MPI_Barrier...
[4] Ending MPI_Barrier
[4] Starting MPI_Finalize...
[0] Ending MPI_Finalize
[2] Ending MPI_Finalize
[3] Ending MPI_Finalize
[4] Ending MPI_Finalize

MPI_Wtime

突然發現, 原來MPI有提供一個函式MPI_Wtime(), 可以用來計算運行過的時間, 單位是秒.
它的回傳值是double, 並且需要確定你的系統環境是MPI_WTIME_IS_GLOBAL是有被定義的.
/* C Example */
#include <mpi.h>
#include <stdio.h>

int main (int argc, char* argv[]){
        int rank, size;
        double t1;
        void *v;
        int flag;

        MPI_Init (&argc, &argv);      /* starts MPI */
        MPI_Comm_rank (MPI_COMM_WORLD, &rank);        /* get current process id */
        MPI_Comm_size (MPI_COMM_WORLD, &size);        /* get number of processes */
        t1 = MPI_Wtime();
        MPI_Attr_get( MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag );
        printf( "Hello world from process %d of %d, time = %f, global time = %d\n", rank, size, MPI_Wtime() - t1, flag);
        MPI_Finalize();
        return 0;
}

MPI & MPE Helloworld

這次來介紹MPI搭配MPE(MPI Parallel Environment)來tracing程式的運作
主程式hello.c跟先前的相同, 程式碼如下:
/* C Example */
#include <mpi.h>
#include <stdio.h>

int main (int argc, char* argv[])
{
  int rank, size;

  MPI_Init (&argc, &argv);      /* starts MPI */
  MPI_Comm_rank (MPI_COMM_WORLD, &rank);        /* get current process id */
  MPI_Comm_size (MPI_COMM_WORLD, &size);        /* get number of processes */
  printf( "Hello world from process %d of %d\n", rank, size );
  MPI_Finalize();
  return 0;
}
Makefile內容如下:
all:
        mpecc -mpitrace -o hello hello.c

mpirun -np 5 ./hello 執行的結果如下:
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
[0] Ending MPI_Init
[0] Starting MPI_Comm_rank...
[0] Ending MPI_Comm_rank
[0] Starting MPI_Comm_size...
[0] Ending MPI_Comm_size
Hello world from process 0 of 5
[0] Starting MPI_Finalize...
[0] Ending MPI_Finalize
[1] Ending MPI_Init
[1] Starting MPI_Comm_rank...
[1] Ending MPI_Comm_rank
[1] Starting MPI_Comm_size...
[1] Ending MPI_Comm_size
Hello world from process 1 of 5
[1] Starting MPI_Finalize...
[1] Ending MPI_Finalize
[2] Ending MPI_Init
[2] Starting MPI_Comm_rank...
[2] Ending MPI_Comm_rank
[2] Starting MPI_Comm_size...
[2] Ending MPI_Comm_size
Hello world from process 2 of 5
[2] Starting MPI_Finalize...
[3] Ending MPI_Init
[3] Starting MPI_Comm_rank...
[3] Ending MPI_Comm_rank
[3] Starting MPI_Comm_size...
[3] Ending MPI_Comm_size
Hello world from process 3 of 5
[3] Starting MPI_Finalize...
[4] Ending MPI_Init
[4] Starting MPI_Comm_rank...
[4] Ending MPI_Comm_rank
[4] Starting MPI_Comm_size...
[4] Ending MPI_Comm_size
Hello world from process 4 of 5
[4] Starting MPI_Finalize...
[2] Ending MPI_Finalize
[3] Ending MPI_Finalize
[4] Ending MPI_Finalize

2013年8月21日 星期三

MPI基本函式介紹

MPI_Init (ierr)
啟動 MPI,所有 MPI 指令之前要有這個初始化指令,唯一個引數是必須宣告成整數的 ierr,如果初始化成功,則 ierr 的傳回值是零。

MPI_Finalize (ierr)
關閉 MPI,結束多個 CPU 協同工作的狀態。正常關閉的話則整數 ierr 的回傳值是零。

MPI_Comm_rank (communicator, my_rank, ierr)
獲得此 CPU 在全體多 CPU 中的排行順序,排名的編號會存在整數變數 my_rank 裏(從零開始),每個參與的 CPU 都會分到一個連號但不重覆的數字(像到郵局辦事領號碼牌那樣)。communicator 是在選通訊裝置,一般都是用預設的 MPI_COMM_WORLD 不用自己改(參見範例),至於 ierr 則是和前面一種作為錯誤或正常的旗標。

MPI_Comm_size (communicator, nproc, ierr)
獲得全體有多少個 CPU 的數目(通常用於切割工作份量的基礎),整數變數 nproc 回傳給每一個 CPU 同樣的數值,即共有多少個 CPU 正在一起工作。ierr 是錯誤回傳檢查用,communicator 的定義與用法跟前面的定義一樣。

MPI_Send (buf, count, datatype, dest, tag, communicator, ierr)
送出(由現在這個 CPU 送出一串資料給另一個 CPU),buf 是指要傳送的那一串資料變數的名稱(也就是第一筆資的位址),count 是資料的長度(從前面定的起點開始算起),datatype 是要被傳送之資料的數值型態,只有幾種常見的固定類型,如 MPI_REAL、MPI_INTEGER 等;整數 dest 是要傳的目的地 CPU 的 rank 編號,至於 整數 tag 則是寫程式的人自已設定的標籤。標籤的功能在這裏可以說明一下,當來源端 CPU 發送資料時,送出來的資料未必會被目的地 CPU 收到相同名稱的變數裏,有可能不止送一包資料,也有可能到達的先後順序會打亂,因此一定要利用標簽來設定每一包資料串有精準被接收到。
MPI_Send 指令是一個阻擋性 (blocking) 的指令,也就是說它要等到收到它在等待的東西才會釋放控制權給主程式去執行下一個指令。

MPI_Recv (buf, count, datatype, source, tag, communicator, status, ierr)
接收。其中前三個引數 buf、count、datatype 與前面定義一樣,souce 是來源 CPU 的編號,tag 則是要與送方指令相同的整數值,作為接收的認證。隨後的 communicator 與 ierr 與前面同。值得注意是 status ,它是用來表示接收的狀態。接收與送出有一點點不同,送出是可以立即動作的,然而接收就並不是下了接收指令就可以馬上進行完成,因為總是要等待資料到達。

MPI_Bcast(buf,n,mpi_datatype,i_src_node,MPI_COMM_WORLD,ierr)
廣播 (Broadcast),意指一個 CPU 放送資料出來,其他 CPU 接收,共同取得該比資料的內容。欲傳送資料的啟始位置是 buf 、長度(資料筆數)是 n 、 i_src_node 是 發送源 之 CPU 編號,其他 mpi_datatype 、MPI_COMM_WORLD、ierr 則是與前面的定義的一樣

MPI_Reduce(buf,result,n,mpi_datatype,mpi_op_type,i_trgt_node, MPI_COMM_WORLD,ierr)
收集各個 CPU 上的結果。其中 mpi_op_type 可以是 MPI_SUM 或 MPI_PRODUCT, 而結果則收集到 i_trgt_node 的 result 變數上(並不是每個 node 的 result 都更新)。

MPI_Get_processor_name (nodename,nchar,ierr)
nodename 是字串變數,它會回傳該 CPU 所在的機器名稱; nchar 是整數,回傳 nodename 內含的字元數

資料來源:

2013年8月19日 星期一

Message Passing Interface

Message Passing Interface (MPI) is a standardized and portable message-passing system designed by a group of researchers from academia and industry to function on a wide variety of parallel computers. The standard defines the syntax and semantics of a core of library routines useful to a wide range of users writing portable message-passing programs. We can use it for creating programmes for distributed computing systems (parallel computing).

MPI特點:
  1. 所有的節點(node,為一台電腦)串接在一起,各自有獨立的記憶體及CPU。
  2. 各節點間會透過互相傳遞訊息來了解彼此的進度。

  3. MPI是利用C語言或Fortran等程式的命令,達到節點間的接收訊息與傳達訊息。

Install MPI environment for you ubuntu
sudo apt-get install libcr-dev mpich2 mpich2-doc

MPI Hello Wrold example

/* C Example */
#include <mpi.h>
#include <stdio.h>
 
int main (int argc, char* argv[])
{
  int rank, size;
 
  MPI_Init (&argc, &argv);      /* starts MPI */
  MPI_Comm_rank (MPI_COMM_WORLD, &rank);        /* get current process id */
  MPI_Comm_size (MPI_COMM_WORLD, &size);        /* get number of processes */
  printf( "Hello world from process %d of %d\n", rank, size );
  MPI_Finalize();
  return 0;
}

mpicc mpi_hello.c -o hello
mpirun -np 2 ./hello

不過有點奇怪, 我目前在我的ubuntu上跑這個code, size回傳居然是1@@
這個部份要再研究一下.
MPI tutorial

資料來源:
http://jetcracker.wordpress.com/2012/03/01/how-to-install-mpi-in-ubuntu/

一個小故事讓我們明白資金流通的意義

“又是炎熱小鎮慵懶的一天。太陽高掛,街道無人,每個人都債台高築,靠信用度日。這時,從外地來了一位有錢的旅客,他進了一家旅館,拿出一張1000 元鈔票放在櫃檯,說想先看看房間,挑一間合適的過夜,就在此人上樓的時候---- 店主抓了這張1000 元鈔,跑到隔壁屠戶那裡支付了他欠的肉錢...