وابستگی داده

یکی از محدودیت­‌های پایه‌­ای در امکان اجرای همروند دستورها یک برنامه، مفهوم ***وابستگی داده ('''به انگلیسی: '''Data Dependency)*** است. برای مثال، یک دستور تا زمانی که داده‌­های مورد نیازش آماده و در دسترس نباشند نمی‌­تواند اجرا شود. در علوم رایانه، وابستگی داده به موقعیتی گفته می‌شود که یک دستور به داده‌های دستورها قبل و یا بعد از خود نیاز دارد.

به‌طور کلی، اگر اجرای هم‌زمان دو دستور ممکن نباشد و اجرای آن‌ها باید به صورت متوالی انجام شود، آن‌ها را ***وابسته*** می‌گوییم.

انواع وابستگی عبارت اند از:
* وابستگی داده 
* وابستگی نام
* وابستگی کنترل
در نظریه کامپایلر، برای تشخیص وابستگی از فنون ***آنالیز وابستگی ('''به انگلیسی: '''[[:en:Dependence_analysis|Dependence Analysis]])*** استفاده می‌شود.

## وابستگی داده
دو دستور S_1 و S_2 را در نظر می‌گیریم که دستور S_2در جایی بعد از دستور S_1 قرار دارد. I(S_i) و O(S_i) را به ترتیب مجموعه خانه‌هایی از حافظه که S_i از آن‌ها می‌خواند و مجموعه خانه‌هایی از حافظه که S_i در آن‌ها می‌نویسد، تعریف می‌کنیم. در این صورت با برقراری شرط زیر که به ***شرط Bernstein*** موسوم است، می‌گوییم S_2 به S_1 وابسته است:بندانگشتی|428x428پیکسل|مثالی از انواع وابستگی داده
[I(S_1)\ \cap \ O(S_2)]\ \cup\  [O(S_1)\ \cap \ I(S_2)]\ \cup\  [O(S_1)\ \cap \ O(S_2)] \ \neq\ \varnothing

به این ترتیب انواع وابستگی داده به صورت زیر تعریف می‌شود:
* **وابستگی جریان (داده):** زمانی که [O(S_1)\ \cap \ I(S_2)] \ \neq \ \varnothing و S_2 از حافظه مشترک چیزی را پس از نوشتن S_1 می‌خواند.
* **پاد وابستگی:** زمانی که [I(S_1)\ \cap \ O(S_2)] \ \neq \ \varnothing و S_2 حافظه مشترک را پس از خواندن S_1 بازنویسی می‌کند.
* **وابستگی خروجی:** زمانی که [O(S_1)\ \cap \ O(S_2)] \ \neq \ \varnothing و S_2 و S_1 هر دو بر روی حافظه مشترک می‌نویسند.
در برخی منابع، نوع چهارمی هم به صورت زیر تعریف می‌شود:
* **وابستگی ورودی:** زمانی که [I(S_1)\ \cap \ I(S_2)] \ \neq \ \varnothing و S_2 و S_1 هر دو از حافظه مشترک می‌خوانند.

### وابستگی جریان
*وابستگی جریان (به انگلیسی: Flow Dependency)* که به آن *وابستگی داده (به انگلیسی: Data Dependency)*، *وابستگی صحیح (به انگلیسی: True Dependency) و خواندن بعد از نوشتن (به انگلیسی: (RAW) Read-after-write)* نیز گفته می‌شود، هنگامی رخ می‌دهد که یک دستور به نتیجه دستوری قبل از خود وابسته باشد. مثال زیر را با فرض اینکه مقدار x و y از قبل محاسبه شده‌است در نظر بگیرید:
```c
a = x + y;
b = 2 * a;
```
در این مثال، دستور دوم به دستور اول وابستگی جریان دارد؛ چرا که از مقدار تولیدی در دستور اول استفاده می‌کند. به این ترتیب در این مثال نمی‌توان دستورها اول و دوم را به صورت هم زمان اجرا کرد.

### پاد وابستگی
*پاد وابستگی (به انگلیسی: Anti-dependency)* که به آن *نوشتن بعد از خواندن (به انگلیسی: Write-after-read (WAR))* نیز گفته می‌شود، هنگامی رخ می‌دهد که یک دستور به داده‌ای نیاز دارد که در دستور بعدی بازنویسی می‌شود. مثال زیر را با فرض اینکه مقدار x و y و z از قبل محاسبه شده‌است در نظر بگیرید:
```c
a = x + y;
b = 2 * a;
a = z + 1;
```
در این مثال دستور دوم به دستور سوم پاد وابستگی دارد. توجه داریم که ترتیب این دستورها نمی‌تواند عوض شود؛ چرا که مقدار نهایی متغیر b را تغییر می‌دهد. همچنین اجرای هم‌زمان دستورها نیز به دلیل احتمال بروز خطا در مقدار نهایی امکان‌پذیر نیست.

پاد وابستگی مثالی از وابستگی نام است؛ به این معنا که وابستگی می‌تواند با تغییر نام برخی متغیرها برطرف شود. برای مثال کد زیر را برای رفع وابستگی مثال قبل در نظر بگیرید:
```c
a2 = x + y;
b = 2 * a2;
a = z + 1;
```
به ابن ترتیب با تغییر نام متغیر a به متغیر جدید a2 در دستورها پیش از بازنویسی آن، پاد وابستگی میان دستورها دوم و سوم از بین رفته‌است و اکنون اجرای هم‌زمان آن‌ها امکان‌پذیر است.

### وابستگی خروجی
*وابستگی خروجی (به انگلیسی: Output Dependency)* که به آن *نوشتن بعد از نوشتن (به انگلیسی: Write-after-write (WAW))* نیز گفته می‌شود، هنگامی رخ می‌دهد که یک متغیر در دو دستور نوشته شود. به بیان دیگر ترتیب اجرای دو دستور تعیین‌کننده مقدار نهایی یک متغیر است. مثال زیر را در نظر بگیرید:
```c
b = 7;
a = 2 * b;
b = 11;
```
در این مثال دستور سوم به دستور اول وابستگی خروجی دارد. توجه داریم که تغییر ترتیب این دستورها موجب تغییر مقدار نهایی متغیرها خواهد شد.

وابستگی خروجی هم مثال دیگری از وابستگی نام است. برای مثال در کد زیر با تغییر نام متغیر b به متغیر b2 در دستورها قبل از بازنویسی آن، وابستگی خروجی مثال قبل برطرف شده‌است:
```c
b2 = 7;
a = 2 * b2;
b = 11;
```


### وابستگی ورودی
*وابستگی ورودی (به انگلیسی: Input Dependency)* که به آن *خواندن بعد از خواندن (به انگلیسی: Read-after-read (RAR))* نیز گفته می‌شود، هنگامی رخ می‌دهد که یک متغیر در دو دستور خوانده شود. مثال زیر را در نظر بگیرید:
```c
b = 7;
a = 2 * b;
c = b;
```
در این مثال دستور سوم به دستور دوم وابستگی ورودی دارد. 

توجه داریم که وابستگی ورودی در عمل مشکلی در اجرای هم‌زمان دستورها ایجاد نمی‌کند. همچنین تغییر ترتیب دستورها نیز قابل انجام است.

به وضوح، وابستگی ورودی نیز نوعی از وابستگی نام است.

## وابستگی نام
وابستگی نام (به انگلیسی: Name Dependency) هنگامی رخ می‌دهد که دو دستور از محل یکسانی از حافظه استفاده می‌کنند اما هیچ جریان داده‌ای میان آن‌ها برقرار نیست. در نتیجه در بسیاری از موارد می‌توان با تغییر نام برخی از متغیرها این وابستگی را از بین برد.

از مهم‌ترین انواع وابستگی‌های نام، وابستگی خروجی و پاد وابستگی هستند. 

## وابستگی کنترل
اگر نتیجه دستور S_1 مشخص‌کننده اجرا و یا عدم اجرای دستور S_2 باشد، آنگاه دستور S_2 به دستور S_1 وابستگی کنترل دارد. مثال زیر را در نظر بگیرید:
```c
if (a == b)
{
    c = 2 * a;
    a = a + b;
}
b = a + b;
```
در این مثال نتیجه دستور اول مشخص می‌کند که دستورها سه و چهار اجرا می‌شوند یا خیر.
بندانگشتی|245x245پیکسل|گراف جریان کنترل ساختار شرطی

### گراف جریان کنترل
برای بیان کردن و نشان دادن دقیق و راحت وابستگی کنترل، معمولاً از مفهوم *[[گراف کنترل جریان|گراف جریان کنترل]] (به انگلیسی: Control flow Graph (CFG))* استفاده می‌شود.

گراف جریان کنترل گرافی جهت‌دار است که مسیرهای مختلفی که اجرای برنامه ممکن است بپیماید را نشان می‌دهد. رأس‌های این گراف را تکه‌های مجزای برنامه تشکیل می‌دهند. در صورتی که امکان انتقال مستقیم از تکه برنامه i به تکه برنامه j وجود داشته‌باشد، یالی از راس i به راس j خواهیم داشت.

## منابع

* allsyllabus Computer_Science Advance Computer Architecture course 
* Wake Forest University CSC346/646 Data Dependency handouts 2015 
* Computer Organization and Architecture
* Colorado State University computer science course CS553Fall06 lecture

رده:کامپایلرها